You are on page 1of 14

MCH553 - Computer Systems and Network Security

MCU Based RSA Encrypted Card Entrance System via RFID Cards and RF
Communication Project Report
Mustafa Alper BALIM
Bursa Technical University

Background
RSA is a useful cryptology method for using projects that use 8 and 16 bit MCUs. In this
project; there are two MCU based control unit. First unit reads the RFID card, and second
unit allows or rejects entries by controlling the door.
Communication will be made by RF communication modules as encrypted via RSA. First unit
will send RFID card ID by encrypting it. Second unit will decrypt received data and will decide
to allow or reject entrance. Then second unit will encrypt the answer of entrance request to
first unit. First unit will decrypt the answer and will allow/reject the user.

Hardware
The system consist of two MCUs , an MIFARE RFID Card Reader and two RF
communication modules. Each RF modules has two part that recieve and transmit data.
Two Arduino Nano based Atmega328 is used as MCUs and proggrammed via Proccesinglike Arduino language.

Scheme: Block diagram of system.

MCUs and RF Modules communicates with each other via software serail communication.
RFID reader communicates via SPI(Serial Peripheral Interface).

Software

Scheme: Central MCU Algorithm.

Scheme: Terminal MCU Algorithm.

Encryption and Decryption Algorithms & Colde Blocks


Encryption or Decryption codes starts with define p and q prime numbers and w that
determining which e and d will be used for encryption and decryption.

Defination of Cryptographic Parameters Block:


1.
2.
3.
4.
5.

Choose two distinct prime numbers p and q.


Compute n = pq
Compute t(n) = t(p)t(q) = (p 1)(q 1)
Choose an integer e such that 1 < e < t(n) and GCD(e, t(n)) = 1
Determine d as ed = 1 (mod t(n))
p=37;
q=41;
w=3;
n=p*q;
t=(p-1)*(q-1);
find_e();

// w= which e and d will be used?


// Finds wth e and d

Find e and d Block.


e must be 1<e<t and GCD(e,t)=1
void find_e()
{
int k=0;
for(int i=2;i<t;i++)
{
if(t%i==0) continue;
flag=is_prime(i);
if(flag==1&&i!=p&&i!=q)
{
e=i;
flag=find_d(e);
if(flag>0)
{
d=flag;
if(k==w)break;
k++;
}}}}

//Turn to start of loop if GCD(e,t)!=1


//is_prime() returns 1 if the number is prime.
//If i is prime and different from p and differen from q
// e=i
//finds d for e

// If iteration reached to w break the loop.

d*e must be equal 1 in mod(t)


int find_d(int x)
{
int k=1;
while(1)
{
k=k+t;
if(k%x==0)
return(k/x);
}}

//k=( k+t) mod(t)


//If appropriated is found return d

Encryption Block:
Encryption block computes the ciphertext c for plaintext p using the public key e for
every character.

= ( )
encrypt(char) function returns two character because ciphertext c that computed is too
large for standart ANSII char variable and values that will be sent by RF module must be
char variable type. First 8 bit of c is kept in cipherText[ctr] and last 8 bit is kept in
cipherText[ctr+1]. cipherText[] array is doubled.
If p and q is choosen too large, c will be larger than 2 character (bytes) and, cipherText
has to be divided into 3 or more. Because of we have limited memory and limited computing
capacity, p and q has to be chosen smaller then 100.

void encrypt(char *plainText, char *cipherText)


{
long m = 1;
int ctr = 0;
for(int i = 0; i <sizeof_plaintext ; i++)
{
for(int j = 0; j<e ; j++)
{
m = (m * plainText[i]) % n;
}
ctr = i * sizeof(int);

//For every character


//m = plainText()^e (mod n)

//How many bytes an integer?

//Equalize first 8 bit of m to cipherText[ctr]


cipherText[ctr] =(char)(m & 0x00ff);
//Shift right second 8 bit of m and equalize to cipherText[ctr+1]
cipherText[ctr + 1] = (char) ((m & 0xff00) >> 8);
m = 1;
}}

Decryption Block:
Decryption block computes the plaintext p for ciphertext cusing the private key d for
every character.

= ( )
decrypt(char) function gets two character that computed by encrypt() function and returns
one character that belongs to plaintext.
Before the computing char array will be reassembled to long variable type by combining
two characters cipherText[ctr] and cipherText[ctr+1]. After computing, computed M is
smaller then c (one byte). But it is still stored as two (or more) bytes. ). M & 0xFF operator
masks first 8 bit of M. And thats equals plainText[i], ith character of plaintext.

void decrypt(char *plainText, char *cipherText)


{
long M = 1;
int temp = 0;
int ctr = 0;
for(int i = 0; i < sizeof_plaintext; i++)

//For every character (plaintext)

ctr = i * sizeof(int);

//How many bytes an integer?

{
//Reassemble the divided cipher characters to temp value.
temp = (((unsigned char)cipherText[ctr + 1] << 8) | (unsigned char)cipherText[ctr]);
for(int j = 0; j < d; j++)
{
M = (M * temp) % n;
}

//M = cipherText()^d (mod n)

// long M converted to charplainText[i]


plainText[i] = (unsigned char)(M & 0xFF);
M = 1;
}
}

Central MCU and Terminal MCU Serial Monitor Screens

Every step of application is printed to Arduino IDE Serial Monitor for observing with serial
communication by USB ports.

Source Codes
Source Code of Central MCU:
#include <VirtualWire.h>
char cipher_msg[200];
char plain[25];
//--------------------------------------int p;
int q;
int n;
int t;
int w;
int e;
int d;
int flag;
//--------------------------------------char recieved_data[200];
boolean stringComplete = false;
String stringRecieved;
void setup()
{
Serial.begin(9600);
vw_set_rx_pin(A5);
vw_set_tx_pin(A4);
vw_rx_start();
p=37;
q=41;
w=3;
n=p*q;
t=(p-1)*(q-1);
find_e();

// w= which e and d will be used?


// Finds wth e and d

//Print parameters.
Serial.print("P=");Serial.println(p);
Serial.print("Q=");Serial.println(q);
Serial.print("N=");Serial.println(n);
Serial.print("T=");Serial.println(t);
Serial.print("E=");Serial.println(e);
Serial.print("D=");Serial.println(d);
}
void loop()
{
uint8_t buf[320];
uint8_t buflen = 320;
vw_setup(2000);
vw_wait_rx(); //Wait if data is not recieved
RF_Read();
if(stringComplete) //If data not recieved
{
Serial.print("ifreli ID Alnd: ");

Serial.println(stringRecieved);
Serial.print("Kart ID zlyor: ");
decrypt(plain, recieved_data);
String plaintxt="";
//CharArray to String Conversation
for(int i = 0; i <= 25; i++) {plaintxt+=plain[i];}
Serial.println(plaintxt);
String Name = "";
//Users
if(plaintxt=="227435119")
else if(plaintxt=="1821504759")
else
if(plaintxt!="not")
else if(plaintxt=="not")

Name="yAlper ";
Name="yMisafir ";
Name="not";

Serial.println("ID Eleti");
Serial.println("ID Elemedi");

char charName[20];
Name.toCharArray(charName,20);
encrypt(charName, cipher_msg);
Serial.print("Cevap ifreleniyor: ");
for(int i = 0; i < buflen; i++) {Serial.print(cipher_msg[i]);}
Serial.println();
const char* mesaj = (const char*) cipher_msg;
vw_setup(2000);
vw_send((uint8_t *)mesaj, 320);
}
Serial.println("///////////////////////////////////////////////////////////
");
Serial.println("");
}
// Read data from RF recieve buffer.
void RF_Read()
{
stringRecieved = "";
recieved_data[320] = {};
char inChar;
uint8_t buf[320];
uint8_t buflen = 320;
if (vw_get_message(buf, &buflen))
{
for (int i = 0; i < buflen; i++)
{
inChar = buf[i];
recieved_data[i]=buf[i];
stringRecieved+=inChar;
}
stringComplete=true;
}
}

void find_e()
{
int k=0;
for(int i=2;i<t;i++)
{
if(t%i==0) continue;
flag=is_prime(i);
if(flag==1&&i!=p&&i!=q)

//Turn to start of loop if GCD(e,t)!=1


//is_prime() returns 1 if the number is
//prime.
//If i is prime and different from p and
//differen from q e=i

{
e=i;
flag=find_d(e);
if(flag>0)
{
d=flag;
if(k==w)break;
k++;
}}}}

//finds d for e

// If iteration reached to w break the loop.

int find_d(int x)
{
int k=1;
while(1)
{
k=k+t;
if(k%x==0)
//k=( k+t) mod(t)
return(k/x); //If appropriated is found return d
}
}
//Returns "1" if "pr" is a prime number.
int is_prime(int pr)
{
int j;
j=sqrt(pr);
for(int i=2;i<=j;i++)
{
if(pr%i==0)
return 0;
}
return 1;
}
void encrypt(char *plainText, char *cipherText)
{
long m = 1;
int ctr = 0;
for(int i = 0; i < 20; i++)
//For every character
{
for(int j = 0; j<e ; j++) //m = plainText()^e (mod n)
{
m = (m * plainText[i]) % n;
}

ctr = i * sizeof(int); //How many bytes an integer?


//Equalize first 8 bit of m to cipherText[ctr]
cipherText[ctr]
= (char) (m & 0x00ff);
//Shift right second 8 bit of m and equalize to
cipherText[ctr+1]
cipherText[ctr + 1] = (char) ((m & 0xff00) >> 8);
m = 1;
}
}
void decrypt(char *plainText, char *cipherText)
{
long M = 1;
int temp = 0;
int ctr = 0;
for(int i = 0; i < 20; i++)
{
ctr = i * sizeof(int);

//For every character (plaintext)


//How many bytes an integer?

//Reassemble the divided cipher characters to temp value.


temp = (((unsigned char)cipherText[ctr + 1] << 8) | (unsigned
char)cipherText[ctr]);
for(int j = 0; j < d; j++) //M = cipherText()^d (mod n)
{
M = (M * temp) % n;
}
// long M converted to charplainText[i]
plainText[i] = (unsigned char)(M & 0xFF);
M = 1;
}
}

Source Code of Terminal MCU:


#include <SPI.h>
#include <MFRC522.h>
#include <VirtualWire.h>
#define door_open A0
#define door_closed A2
char cipher_msg[200];
char plain[25];
//--------------------------------------int p;
int q;
int n;
int t;
int w;
int e;
int d;
int flag;
//--------------------------------------#define RST_PIN
#define SS_PIN

9
10

MFRC522 mfrc522(SS_PIN, RST_PIN);


MFRC522::MIFARE_Key key;
char gelen_veri[200];
boolean stringComplete = false;
String stringGelen;
byte readCard[4];
char cardID[30];
String stringID="";
int sizeID;
void setup()
{
pinMode(door_open, OUTPUT);
pinMode(door_closed, OUTPUT);
digitalWrite(door_open, LOW);
digitalWrite(door_closed, HIGH);
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
vw_set_rx_pin(A5);
vw_set_tx_pin(A4);
vw_rx_start();
p=37;
q=41;
w=3;
n=p*q;
t=(p-1)*(q-1);
find_e();

// w= which e and d will be used?


// Finds wth e and d

//Print parameters.
Serial.print("P=");Serial.println(p);
Serial.print("Q=");Serial.println(q);
Serial.print("N=");Serial.println(n);
Serial.print("T=");Serial.println(t);
Serial.print("E=");Serial.println(e);
Serial.print("D=");Serial.println(d);
}
void loop()
{
uint8_t buf[320];
uint8_t buflen = 320;
//Wait for new card
if ( ! mfrc522.PICC_IsNewCardPresent()) return;
if ( ! mfrc522.PICC_ReadCardSerial()) return;
Serial.print("Kart ID Okunuyor: ");
ID_Read();
mfrc522.PICC_HaltA();
Serial.println(stringID);
Serial.print("Kart ID ifreleniyor: ");
encrypt( cardID, cipher_msg);
for(int i = 0; i < buflen; i++)
Serial.print(cipher_msg[i]);
Serial.println();
Serial.println("ifreli ID Gnderiliyor...");
const char* mesaj = (const char*) cipher_msg;
vw_setup(2000);
vw_send((uint8_t *)mesaj, buflen);
Serial.println("Giri zni Bekleniyor");
delay(4500); //Wait for Central MCU's Answer
RF_Read(); // Read data from RF recieve buffer.
Serial.println("Cevap Alnd");
decrypt(plain, gelen_veri);
String plaintxt="";
for(int i = 0; i <= plaintxt.length()+1; i++)
plaintxt+=plain[i];
if(plaintxt=="not")
Serial.println("Giri zni Verilmedi");
else if(plain[0]=='y')
{
Serial.print("Giri zni Verildi => ");
Serial.print("Kullanc:");
for(int i=1;i<25;i++) Serial.print(plain[i]);
Serial.println("");
digitalWrite(door_open, HIGH);
digitalWrite(door_closed, LOW);
}
plain[0]='x';
Serial.println("///////////////////////////////////////////////////////////
");

Serial.println("");
delay(3000);
digitalWrite(door_open, LOW);
//Open Door
digitalWrite(door_closed, HIGH); // Close Door
}
//Read Card ID and convert to char array and string
void ID_Read()
{
stringID="";
for (int i = 0; i < 4; i++)
{
readCard[i] = mfrc522.uid.uidByte[i];
stringID+=readCard[i];
}
sizeID=stringID.length()+1;
stringID.toCharArray(cardID, sizeID ) ;
}
//// Read data from RF recieve buffer and convert to string and char array.
void RF_Read()
{
uint8_t buf[320];
uint8_t buflen = 320;
stringGelen = "";
gelen_veri[320] = {};
char inChar;
if (vw_get_message(buf, &buflen))
{
for (int i = 0; i < buflen; i++)
{
inChar = buf[i];
gelen_veri[i]=buf[i];
stringGelen+=inChar;
}
stringComplete=true;
}}
void find_e()
{
int k=0;
for(int i=2;i<t;i++)
{
if(t%i==0) continue;
flag=is_prime(i);
if(flag==1&&i!=p&&i!=q)
{
e=i;
flag=find_d(e);
if(flag>0)
{
d=flag;
if(k==w)break;
k++;
}}}}

int find_d(int x)
{
int k=1;
while(1)
{
k=k+t;
if(k%x==0)
return(k/x);
}}
int is_prime(int pr)
{
int j;
j=sqrt(pr);
for(int i=2;i<=j;i++)
{
if(pr%i==0)
return 0;
}
return 1;
}
void encrypt(char *plainText, char *cipherText)
{
long m = 1;
int ctr = 0;
for(int i = 0; i <sizeID ; i++)
{
for(int j = 0; j<e ; j++)
{
m = (m * plainText[i]) % n;
}
ctr = i * sizeof(int);
cipherText[ctr]
= (char) (m & 0x00ff);
cipherText[ctr + 1] = (char) ((m & 0xff00) >> 8);
m = 1;
}}
void decrypt(char *plainText, char *cipherText)
{
long M = 1;
int temp = 0;
int ctr = 0;
//re-assemble char array to array of int
for(int i = 0; i < sizeID; i++) {
ctr = i * sizeof(int);
temp = (((unsigned char)cipherText[ctr + 1] << 8) | (unsigned
char)cipherText[ctr]);
for(int j = 0; j < d; j++) {
M = (M * temp) % n;
}
plainText[i] = (unsigned char)(M & 0xFF);
M = 1;
}}

You might also like