Yüksek lisans kriptografi dersi için hazırladığım projeyi yayınlıyorum. Ders İngilizce olduğu için raporu da İngilizce yazmıştım. Proje ile ilgili tüm sorularınızı yorum kısmından gönderebilirsiniz. İlerleyen zamanlarda Türkçe’ye çevirebilirim.
Projeye Türkçe bir özet yapmak gerekirse; RSA şifreleme, RF haberleşme, Arduino, RFID teknolojileri / yöntemlerini kullanarak basit bir kartlı geçiş sistemi diyebiliriz.
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 MCU’s. 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 MCU’s , 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 MCU’s and proggrammed via Proccesinglike Arduino language.

System Block Scheme
MCU’s and RF Modules communicates with each other via software serail communication. RFID reader communicates via SPI(Serial Peripheral Interface).
Software

Central MCU Flow Chart

Terminal MCU Flow Chart
Encyrption and Decryption Algorithms & Colde Blocks
Encyrption 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. Choose two distinct prime numbers p and q.
2. Compute n = pq
3. Compute t(n) = t(p)t(q) = (p − 1)(q − 1)
4. Choose an integer e such that 1 < e < t(n) and GCD(e, t(n)) = 1
5. Determine d as ed = 1 (mod t(n))
1 2 3 4 5 6 |
p=37; q=41; w=3; // w= which e and d will be used? n=p*q; t=(p-1)*(q-1); find_e(); // Finds “w”th “e” and “d” |
Find “e” and “d” Block.
“e” must be 1<e<t and GCD(e,t)=1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
p=37; q=41; w=3; // w= which e and d will be used? n=p*q; t=(p-1)*(q-1); find_e(); // Finds “w”th “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; //Turn to start of loop if GCD(e,t)!=1 flag=is_prime(i); //is_prime() returns ”1” if the number is prime. if(flag==1&&i!=p&&i!=q) //If “i” is prime and different from “p” and differen from “q” { // e=i e=i; flag=find_d(e); //finds “d” for “e” if(flag>0) { d=flag; if(k==w)break; // If iteration reached to “w” break the loop. k++; }}}} |
“d*e” must be equal “1” in mod(t)
1 2 3 4 5 6 7 8 9 |
int find_d(int x) { int k=1; while(1) { k=k+t; //k=( k+t) mod(t) if(k%x==0) //If appropriate”d” is found return “d” return(k/x); }} |
Encyrption Block:
Encyrption block computes the ciphertext “c” for plaintext “p” using the public key “e” for every character.
? = ?^? (??? ?)
“encyrpt(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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void encrypt(char *plainText, char *cipherText) { long m = 1; int ctr = 0; for(int i = 0; i <sizeof_plaintext ; 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; }} |
Decyrption Block:
Decyrption block computes the plaintext “p” for ciphertext “c”using the private key “d” for every character.
? = ?^? (??? ?)
“decyrpt(char)” function gets two character that computed by ”encyrpt()” 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” operatormasks first 8 bit of “M”. And thats equals “plainText[i]”, “i”th character of plaintext.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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 = cipherText()^d (mod n) { M = (M * temp) % n; } // “long” “M” converted to “char”plainText[i] plainText[i] = (unsigned char)(M & 0xFF); M = 1; } } |
Every step of application is printed to Arduino IDE Serial Monitor for observing with serial communication by USB ports.
Central MCU Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
#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; // w= which e and d will be used? n=p*q; t=(p-1)*(q-1); find_e(); // Finds “w”th “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 Alındı: "); Serial.println(stringRecieved); Serial.print("Kart ID Çözülüyor: "); 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") Name="yAlper "; else if(plaintxt=="1821504759") Name="yMisafir "; else Name="not"; if(plaintxt!="not") Serial.println("ID Eşleşti"); else if(plaintxt=="not") Serial.println("ID Eşleşmedi"); 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; //Turn to start of loop if GCD(e,t)!=1 flag=is_prime(i); //is_prime() returns ”1” if the number is //prime. if(flag==1&&i!=p&&i!=q) //If “i” is prime and different from “p” and //differen from “q” e=i { e=i; flag=find_d(e); //finds “d” for “e” if(flag>0) { d=flag; if(k==w)break; // If iteration reached to “w” break the loop. k++; }}}} 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 appropriate”d” 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++) //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 = cipherText()^d (mod n) { M = (M * temp) % n; } // “long” “M” converted to “char”plainText[i] plainText[i] = (unsigned char)(M & 0xFF); M = 1; } } |
Terminal MCU Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
#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 9 #define SS_PIN 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; // w= which e and d will be used? n=p*q; t=(p-1)*(q-1); find_e(); // Finds “w”th “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 Gönderiliyor..."); 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 Alındı"); 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("Kullanıcı:"); 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; }} |