---
# System prepended metadata

title: IoT project - Understanding RFID security

---

Author: Simon Karlsson, sk224js

This project was the final assignment for the course Applied Internet of Things (1DT305) at Linnaeus University. It's not a finished product but rather a project focused on understanding how RFID based security systems works. Real-world applications are advised against. 
As you may already know RFID stands for Radio-frequency identification and is amongs other things used in access cards, door tags, theft prevention stickers.

The time taken for the project could be divided into several steps, many of which could be automated with simple scripts (which I unfortunately cannot provide):

1. Setting up the environment
   - 10 minutes to set up the IDE
   - 15 minutes to download the relevant packages

2. Wiring and hardware
   - 30 minutes to solder headers
   - 30 minutes to wire everything up
  
3. Setting up the stack
   - 10 minutes to install Docker
   - 5 minutes to install a Docker image of the database
   - 20 minutes to install the database server on my machine and connecting it to the Docker image
   - 5 minutes to install MQTT broker image
   - 10 minutes to configure said image
   - 10 minutes to install Node-Red image and setting it up with MQTT.
   
4. Code related stuff
   - 5 minutes to change the variables for WIFI and MQTT
   - 5 minutes uploading the code to the Pico
   - 5 minutes entering values from RFID tags into DB

All together it's about 3 hours of work, proper usage of Docker could likely eliminate lots of time spend on configuring settings manually.
It actually took a lot longer due to figuring things out as you go, but we're here to learn so that's part of the journey. 

# Objective
As mentioned before the project was mostly about learning and not as much about real world applications.

Part of the reason for choosing to design a RFID based security system was because I had the parts already available but it had also been on my mind for a while when working on other projects in different courses. 

There's finnished products already being sold doing excatly the same thing, more securely and better coded so this serves only as a learning tool. But if you really would insist on practical applications then it could be used together with a locking mechanism to construct a lockbox to keep your candy safe from siblings or children.

One of the insigts I was most hyped for was related to encrypting the data and managing a password database. But learning about the potential vulnerbilities in this type of devices also spark some interest.

# Material
| Component | Price | Additional info |
| -------- | -------- | -------- |
| 4x4 matrix keypad     | [29 SEK](https://pchbutik.se/sv/hid/411-tangent-matris-med-4x4-knappar-passar-arduino.html)     | 16 buttons wired together on a PCB     |
|RFID-RC522|[49 SEK](https://pchbutik.se/sv/tradloest/457-rfid-lasare-for-kort-och-tags-passar-arduino.html)|A RFID reader with two tags|
|Raspberry Pi Pico W|[98 SEK](https://www.electrokit.com/produkt/raspberry-pi-pico-w/)|A useful development board with WiFi|
|Green LED|[8 SEK](https://www.electrokit.com/produkt/led-5mm-gron-inbyggt-motstand-5v/)|LEDs easily burn out so be sure to get some extra|
|Red LED|[8 SEK](https://www.electrokit.com/produkt/led-5mm-rod-inbyggt-motstand-5v/)||
|MtM jumper wires|[29 SEK](https://www.electrokit.com/produkt/labbsladd-20-pin-15cm-hane-hane/)|A strip of male to male wires you can separate|
|MtF jumper wires|[29 SEK](https://www.electrokit.com/produkt/labbsladd-20-pin-15cm-hona-hane/)|Same as above but male to female wires|
|breadboard|[69 SEK](https://www.electrokit.com/produkt/kopplingsdack-840-anslutningar/)|840 hole solderless breadboard|
|220 ohm resistors|[3 SEK](https://www.electrokit.com/produkt/motstand-metallfilm-0-6w-1-220ohm-220r/)|just a simple resistor, could easily be replaced|



For this project I used a 4x4 matrix keypad, a RFID reader, 2 220ohm resistors, 2 LEDs colored red and green and a Raspberry Pi Pico W. Also a lot of jumper wires(17) and a breadboard

The 4x4 matrix keypad I used was basically just a PCB with 16 push buttons wired together. 
![](https://hackmd.io/_uploads/HyboGlEth.jpg)

The RFID reader, RFID-RC522 to be specific is a common module often seen in other projects. It uses a 13.56MHz electromagnetic field to communicate with RFID tags at the same time as it communicates over SPI with the Pice. It's also capable to use I2C and UART but SPI seems more common.
It's range is about 3 cm but the technical specifications says 10 cm. It has a IRQ pin which I have yet to explore, that enables you to put your Pico to sleep and simply use interrupts from the RFID reader to wake it up again.
![](https://hackmd.io/_uploads/rJZszg4K2.jpg)

Nothing really special about the resistors, 220ohm was chosen to prevent the LEDs from burning out and protecting the ports on the Pico, higher resistance could have been used but would have dimmed the light somewhat.
The LEDs was used as actuators to signal if the card/password was denied or if everything was correct.

Raspberry Pi Pico W, a development board from the Raspberry Pi Foundation, it operates at 3.3V and comes equipped with Wifi and Bluetooth capabilities. It comes in both W and WH varieties, where W stands for wireless and H stands for headers. I bought a Pico W from the beginning since I'm comfortable soldering the headers myself. 

The jumper wires divided into 8 FtM and 9 MtM wires.

The breadboard was on the larger side with 840 holes, I chose that one mostly out of convenience but you can easily do the project with a smaller one.

# Computer setup

I opted for the use of the Thonny IDE for it's simplicity to use and install. Not bothering with any plugins and such saved me lots of headache. 

When getting started with MicroPython on a Raspberry Pi Pico the first step needs you to install firware, it comes in a [uf2 file](https://micropython.org/download/rp2-pico-w/), to mount it you first have to hold down the BOOTSEL button on the Pico while mounting it by USB to a pc, that opens it up kinda like a thumbdrive where you simply drop the uf2 file.
- Thonny also have inbuilt functionallity to install firmware but they don't have as good support for different boards so you would have to pick the firmware for the regular Pico instead of Pico W making it unable to use Wifi.

When you're done with the firmware that you simply pull out the cable and plug it back in again to boot the board in regular mode.

To start out with Thonny you first go to the "Run" meny at the top of the screen then chose "Select interpreter..." which opens a new window, there you go to the "Interpreter" tab and selects "MicroPython (Raspberry Pi Pico)" in the first dropdown meny and the port used by the Pico in the second dropdown then you simply press OK. This step is so that Thonny recognizes what to look for properly.

As most IDEs Thonny comes with some plugins but since I'm not using any of them I can't tell much about them.

When you program a Pico you plug it in **without** holding the BOOTSEL button, Thonny will usually not display the filestructure directly so you will have to push the Stop/Restart button first in the top menys or by pressing Ctrl + F2. This will stop the program and display the filestructure of the Pico in the left side of the screen. To Start coding you start a new file (Ctrl + N), when you're done writing the code make sure to save it as main.py or boot.py to have the Pico run it automatically. Starting out make sure to notice the window bellow your code, the shell tab lets you play around with the REPL(Read–eval–print loop). The REPL enables you to test out code by simply entering it one line at a time and when you encounter an error it doesn't break your whole code but you can simple retype that line and start figuring out what whent wrong. I usually use the REPL to access the built in functions in python such as type() or dir() for when I need to know more about how to handle some data. 

# Putting everything together 

![](https://hackmd.io/_uploads/HJmF5hlYh.png)

The RFID reader was connected to pin 20 to 26, as well as 3V3(OUT) and ground.
The 8 pins of the keypad connected to the pin 4 to 12 which had the GPIOs conveniently placed in groups of four. 
Lastly the LEDs connected to the GPIOs in the corner through the resistors so that I don't have to increase the mess of wires further.

# Platform
Part of the project was deciding on a hosting platform but even with all the cloud based solutions out there only one that made sense to me was to host it on my own, that's due to security reasons. While a external site might offer greater protections against hacking it also comes with the liability of sending password related data outside of the local network. 
I connected it all together with Mosquitto, Node-Red, PostgreSQL and hosted it in Docker on my laptop.
Mosquitto was my MQTT broker handling the communication.
Node-Red is graphical programming tool that I used to create "flows" for how the communications went, Node-Red subscribed and published to MQTT topics but also connected them to the database PostgreSQL which stored the RFID tags and corresponding passwords.

# The code
 ![](https://hackmd.io/_uploads/ryi2qWEKh.png)
For starters I used a separate file for network credentials,
WIFI_SSID is simply the name of the WiFi you want to connect to.
WIFI_PASS is the password
MQTT_SERVER is actually the IP for the laptop where I hosted the dockerized image of Mosquitto, Mosquitto itself has a separate IP within Docker that you will have to figure out on your own. *The 10.0.0.0–10.255.255.255 range of IPs are withing a network so no worries sharing that one.*
CLIENT_ID is the device name, basically the identifier if I want to make a system containing multiple devices.


![](https://hackmd.io/_uploads/BylkgMNYn.png)
For the main part of the code I hade a loop for connecting to the WiFi with a nested loop that scanned for RFID tags, the scan method itself was also a loop so the pico would continue to scan until it finds something which it then sends to the MQTT server with my pubsub method.

![](https://hackmd.io/_uploads/S1k1uf4Yh.png)
The scan method are just borrowed code modified to returning the ID instead of just printing it out. I can't really take any credit for that inovation.

![](https://hackmd.io/_uploads/HJTibfNF2.png)
The pubsub method was created by mashing together separate methods for publishing and subscribing and still have lots of room for improvement.
But what it does is basically connecting to the MQTT server and selecting a topic to listen to then it publishes to RFID to the "scan_card" topic followed by calling the wait_msg method. Wait msg comes from the umqtt.simple library but it's basically a loop that waits for messages. In case of networking problems and such it has a tendancy to break the system so switching to the check_msg that also comes with the library would be a good idea.

![](https://hackmd.io/_uploads/HyPSNG4Yh.png)
After a while the Pico hopefully gets a pincode back, the pincode is then compared to a pincode read from the keypad. Then either the green or the red LED turns on depending on the result.


![](https://hackmd.io/_uploads/SJt7kMEF3.png)
For the keypad I chose to modify preexisting code that looped through all the buttons in a infinite loop and turned it into two methods, first one simply does one loop and checks if any button has been pressed, then adds it to a string i passed as in parameter.
The seconds method controls how many keypresses you will record and a timelimit so that the pico isn't stuck scanning keypresses forever when there is no one around. Then it just calls for the first method a number of times until either condition has been met.

![](https://hackmd.io/_uploads/S1Q6HMEt2.png)
Lastly the imports: the umqtt folder and simple.py are related to MQTT, there's more libraries out there with better error handling etc but I just wanted something simple.
mfrc522.py is for the RFID reader itself, as with simple.py it's filled with advanced stuff that you don't wanna poke around in yourself.


# Transmitting the data / connectivity
I went with WiFi to a local server on my laptop.
The communication used the MQTT protocol for Pico - Laptop comunication. MQTT are designed for low bandwith to the packet sizes are quite small with a tiny header cotaining info where the packet is going and, some info about how much data the packet contains and the payload containing all the good stuff we want to transmit.

# Presenting the data
My presentation of data was left rather rudimental since I don't believe there is much use in this situation other than recordning at what time there's most activity in a building etc. ![](https://hackmd.io/_uploads/rkMS0pQFn.png)
I simply used one of the dashboard palettes that's available in Node-Red to do it. 
For actual uses I believe logging ID, ID-found, password match(if the password was correctly entered or not), time and device/location then putting them all in a table in a database. That's to record suspicious activity and limit the suspects in case of theft in a building.
I didn't go for that level of logging myself but thought it might be a good idea to get my database management system running on my laptop as a easy to use GUI interfacing with the database running in a Docker image. ![password table in PostgreSQL](https://hackmd.io/_uploads/B1s5HCQtn.png), as usual for databases you query it with SQL prompts. The database are by default set to log the number of queries done but that could likely be expanded upon in the system if you so wishes.



# Finalizing the design
I got the project working as supposed but I had to scrap a bunch of initial plans in the process. That leaves some areas of improvement for the future.
* Hardware improvements
    - Buzzer
    - Actuator of some kind, either a servo or just connecting it to a locking mechanism.
    - improved wiring/cable managment, I would consider switching to a experiment card instead of the breadbord and solder on it instead of having all those wires all over the place.
    - A project case, either a 3d printed box or just reusing a icecream box.
* Software improvements
    - Hashing, hashing the passwords on the device so that you don't store passwords in plaintext in the database. Generating and storing salt could easily be done in the database. 
    - Changes of the dataflow, rather than simply scanning a ID and returning a password to the pico which simply checks if two strings are the same. The better way of doing it would be to scan ID, return salt or nothing if the ID isn't inte database, hashing and salting on the Pico, Sending the hashed password to the database for validation and get a return which tells the Pico if it's correct.
    - Threading, improve the use of MQTT by handling the listening to MQTT topics on a separate thread instead of simply stopping everything and wait for a message. (Wouldn't actually be noticable by the user, but it's a good exercise if you want to learn more about coding.)
    - Putting the device to sleep and waking it with interrupts from the RFID reader
    - Turning the Pico into a access point and hosting a webpage for setting the passwords and addresses for WiFi + MQTT in there the first time the device starts. 
* Setup improvements
    - Moving the hosting to a Raspberry Pi rather than hosting on laptop.
    - Switching to static IP addresses for the dockerized programs so that the IPs doesn't change if I shut it down.
    - Using Docker Compose instead of separate Docker Images
    


 [Video of the project in action](https://www.youtube.com/shorts/jO28DFxof9w)


![](https://hackmd.io/_uploads/Hy1sMl4Yh.jpg)
![](https://hackmd.io/_uploads/rke1jfeNFh.jpg)
