This is a project linked to an article Raspberry Pi e Smart Card Mifare Classic 1K: Realizzare un sistema di accesso publish on my blog. What is described in this README should be enough to make you understand the intentions of this project, I leave the rest to your curiosity.
This project was born with the aim of providing a complete example (hardware and software) on how it is possible to create a simple access system using contactless Smart Cards and the Raspberry Pi. The figure below shows the hardware diagram of the Smart Card access solution.
The scenario I created is the one that each of us experiences almost every day, that is, with our hands a Smart Card to gain access to an opening, which could for example be a door to a hotel room.
Figure 1 - Hardware diagram of the Smart Card access solution (Smart Card icon from https://www.smartcardfocus.com/)
The MIFARE Classic® 1K contactless is predicated on NXP MF1 IC S50, which is connected to a coil with a couple of turns then embedded into the plastic to make the passive contactless open-end credit. The communication layer (MIFARE RF Interface) complies with part 2 and three of the ISO/IEC14443A standard. This type of card is a good choice for classic applications such as public transport ticketing and can also be used for several other applications (door opening systems and the like).
The Smart Card Reader must be compliant with the standards indicated in the diagram in figure 1. In my case I used the Bit4id miniLector CIE reader connected to the Raspberry Pi via the USB port. The technical name of the reader I used is: BIT4ID miniLector AIR NFC v3.
A four-relay module managed through the GPIO ports is connected to the Raspberry Pi. In our scenario, the relays represent the actuators necessary to open the doors of the hotel where we are guests.
Figure 2 illustrates the simplified process (in BPMN notation) of what happens when a guest is received by the hotel staff. Of the whole process, only the service task (indicated in red) is the object of the software implementation.
Figure 2 - Simplified process of receiving the guest at the hotel.
The process of figure 3 instead shows what happens when the guest asks to enter his room through the use of the electronic key by placing it on the reader. Of the whole process, only the service task (indicated in red) is the object of the software implementation.
Figure 3 - Room access process
The software of this project written in Python implements the service tasks indicated in the processes of figure 2 and figure 3. In particular, the entry points are:
setup_smart_card.py
. Python script that implements the service task indicated in the process of figure 2. This script receives a series of input data (number of identity document, room number, name and surname of the guest). Of the received data, some are stored on the Smart Card (identity document number) and others on the database (in this case MongoDB).access_via_smart_card.py
. Python script that implements the service task indicated in the process of figure 3. This script extracts from the Smart Card the identification of the same and the number of the identity document, then uses this data to understand if the guest can have access to his room.
Table 1 shows the data managed by the Smart Card. The UID is actually proper to the Smart Card, however, the
Identification Number attribute is written during the setup phase by the setup_smart_card.py
script and read during the access
request phase by the access_via_smart_card.py
script.
Attribute Name | Description | Type |
---|---|---|
UID | Smart Card ID assigned by the manufacturer. In this case we use the 4-byte NUID. | Byte(4) |
Identification Number | Number (which can also be alphanumeric) of the guest's identity document. | Byte(16) |
Table 1 - Data that is stored on the Smart Card.
Table 2 shows the data managed by the database (MondoDB). The scope column indicates which python script used (for reading or writing) the attribute, therefore, identifies on which process it is used (setup procedure or access procedure).
Console 3 shows the document created on the database during the Smart Card setup phase. Console 5 shows the document updated when requesting access via the Smart Card.
Attribute Name | Scope | Description | Type |
---|---|---|---|
createDate | setup_smart_card.py | Date when document/record was registered on the system. | Date Time with Time Zone (ISO Format) |
modifiedDate | access_via_smart_card.py | Date whose purpose is to track each document / record update. | Date Time with Time Zone (ISO Format) |
firstAccess | access_via_smart_card.py | Date representing the first access to the system via the Smart Card. | Date Time with Time Zone (ISO Format) |
lastAccess | access_via_smart_card.py | Date representing the last access to the system via the Smart Card. | Date Time with Time Zone (ISO Format) |
smartCardInitDate | setup_smart_card.py | Date when the Smart Card was registered on the system. | Date Time with Time Zone (ISO Format) |
smartCardId | setup_smart_card.py, access_via_smart_card.py | UID (4 byte) of the Smart Card | String |
smartCardEnabled | setup_smart_card.py, access_via_smart_card.py | Indicates if the Smart Card is enabled (true), false otherwise. | Boolean |
documentId | setup_smart_card.py, access_via_smart_card.py | Number (which can also be alphanumeric) of the guest's identity document. | String |
roomNumber | setup_smart_card.py, access_via_smart_card.py | Number of the assigned room | Int |
countAccess | setup_smart_card.py, access_via_smart_card.py | Number of successful accesses. | Int |
firstName | setup_smart_card.py | Name of the guest to whom the Smart Card is assigned. | String |
lastName | setup_smart_card.py | Lastaname of the guest to whom the Smart Card is assigned. | String |
Table 2 - Data that is stored on the database (MongoDB).
- Raspberry Pi 4 Model B 8GByte RAM
- MicroSD Card (min 8GByte)
- Elegoo 4 Channel DC 5V Modulo Relay
- Bit4id miniLector CIE
- Mifare Classic 1K
- Mifare Classic 1K RfId Tag
- Raspberry Pi OS (64bit)
- Python 3.9.x
- Docker 20.10.12
- Development Tools (make, gcc) (install or update via
sudo apt install build-essential
)
Figure 4 shows the wiring diagram for connecting the four relay module to the GPIO pins of the Raspberry Pi 4. I remember that the Smart Card reader is connected via USB to the Raspberry Pi 4, for this reason it has not been included in the wiring diagram.
Figure 4 - Wiring diagram Raspberry Pi and Relays Module
The fundamental steps to be able to try the solution immediately are indicated below.
- Login to your Raspberry Pi
- Clone project, install the python requirements and prepare MongoDB
- Smart Card Initialization
- Run the Smart Card Access Tool
To perform the reading and writing operations on the Smart Card, an authentication key is required, the default value
is FFFFFFFFFFFF
. This key must be passed to both Python scripts via the -a
or --authentication-key
option. For
details on accepted options, use the -h
or --help
option.
# 1. Clone the repository
$ git clone https://github.com/amusarra/smartcard-contactless-raspberry-pi.git
$ cd smartcard-contactless-raspberry-pi
# 2. Install the Python requirements
$ make
# 3. Docker pull and run MongoDB 4.4.12
$ docker pull mongo:4.4.12
$ docker run -d -p 27017-27019:27017-27019 --name mongodb mongo:4.4.12
# 4. Check MongoDB logs and howto access to the MongoDB console (optional task)
$ docker exec -it mongodb bash
# Inside the MongoDB Docker Container
root@0d21da235b0d:/# mongo
Console 1 - Clone project, install the python requirements and prepare MongoDB
# 1. Smart Card Initialization
# a) Store Identity document number (example: identity card, driving license,
# social security number, passport number) on Smart Card
# b) Association of the Smart Card to the specific person and assignment of the room.
$ cd smartcard-contactless-raspberry-pi
# Setup Smart Card for Antonio Musarra with identity card DA789876DF and assign room number one (1)
$ ./setup_smart_card.py -a FFFFFFFFFFFF -i DA789876DF -s --firstname Antonio --lastname Musarra -r 1
Console 2 - Smart Card Initialization
Figure 1 - Run the Smart Card Init Tool to init the first Smart Card
# 1. Run the mongo console from Docker Container
root@0d21da235b0d:/# mongo
# 2. Use the SmartCardAccessCrudDB and view the SmartCardAccess collection
> use SmartCardAccessCrudDB
> db.SmartCardAccess.find().pretty()
{
"_id" : ObjectId("62195fbf93c42ff88754734e"),
"createDate" : "2022-02-25T23:01:19.682355Z",
"firstname" : "Antonio",
"lastname" : "Musarra",
"documentId" : "DA789876DF",
"smartCardEnabled" : "true",
"smartCardId" : "B4 90 90 1E",
"smartCardInitDate" : "2022-02-25T23:01:19.682582Z",
"roomNumber" : 1,
"countAccess" : 0
}
Console 3 - Check entry on MongoDB
# 1. Start the Smart Card Access Tool
# a) Read the Identification Number from Smart Card
# b) Check on MongoDB if the Smart Card is paired and enabled
# c) If the association is valid then it opens the door of the room to
# which the card is associated. Opening corresponds to the activation
# of the relay which is deactivated after five seconds.
$ cd smartcard-contactless-raspberry-pi
# Run the Smart Card Access Tool
$ ./access_via_smart_card.py -a FFFFFFFFFFFF
Console 4 - Run the Smart Card Access Tool
Figure 2 - Run the Smart Card Access Tool
> db.SmartCardAccess.find().pretty()
{
"_id" : ObjectId("62195fbf93c42ff88754734e"),
"createDate" : "2022-02-25T23:01:19.682355Z",
"firstname" : "Antonio",
"lastname" : "Musarra",
"documentId" : "DA789876DF",
"smartCardEnabled" : "true",
"smartCardId" : "B4 90 90 1E",
"smartCardInitDate" : "2022-02-25T23:01:19.682582Z",
"roomNumber" : 1,
"countAccess" : 5,
"firstAccess" : "2022-02-25T23:15:36.523275Z",
"lastAccess" : "2022-02-25T23:27:33.645680Z",
"modifiedDate" : "2022-02-25T23:27:33.645727Z"
}
{
"_id" : ObjectId("62196645c6b265cd472d58ca"),
"createDate" : "2022-02-25T23:29:09.869289Z",
"firstname" : "Valentina",
"lastname" : "Musarra",
"documentId" : "MU589876XD",
"smartCardEnabled" : "true",
"smartCardId" : "13 9E 55 73",
"smartCardInitDate" : "2022-02-25T23:29:09.869317Z",
"roomNumber" : 2,
"countAccess" : 3,
"firstAccess" : "2022-02-25T23:29:18.392172Z",
"lastAccess" : "2022-02-25T23:29:40.846213Z",
"modifiedDate" : "2022-02-25T23:29:40.846276Z"
}
Console 5 - Data display to check for updates following accesses
The following two animations show the Smart Tool Init and the Smart Card Access Tool in action, making the operation and processes indicated above clearer.
Animation 1 - Smart Card Init tool in action (on asciinema https://asciinema.org/a/475795)
Animation 2 - Smart Card Access tool in action (on asciiname https://asciinema.org/a/475797)
The documentation of the project is available in the docs
folder. The documentation is written in Markdown format
and can be read directly on GitHub pages at the following link: Smart Card Contactless Raspberry Pi GitHub Pages
Also, the documentation is available in PDF format at the following link: eBook - Smart Card Contactless Raspberry Pi.
The source code of the documentation is available in the docs/asciidoc
folder of the project.
The GitHub Pages are generated using the MkDocs tool and the
Material for MkDocs theme using the GitHub Actions workflow
defined in the .github/workflows/publish_doc_to_gh_pages.yml
file.
The eBook is generated using the Asciidoctor tool and in particular the Asciidoctor PDF. The requirement to generate the PDF is to have the Asciidoctor PDF; the instructions for installing this tool are available at the following link: Asciidoctor PDF.
The command to generate the PDF is as follows:
# Generate the PDF. The command must be executed from the root of the project.
# The output file is saved in the docs/asciidoc folder.
# The <ebook-file-name.pdf> must be replaced with the desired name of the PDF file.
asciidoctor-pdf -o docs/asciidoc/<ebook-file-name.pdf> docs/asciidoc/index.adoc
Console 6 - Generate the PDF of the documentation
Also, exist the GitHub Actions workflow defined in the .github/workflows/generate-pdf.yml
file that generates the PDF
of the documentation and commits it to the repository in the docs/asciidoc
folder.