شبیهسازی کاربرد RFID برای دسترسی به یک سایت امن مشخص میکند که کدام کارتهای بدون تماس معتبر یا غیرمعتبر هستند
برای شبیهسازی کاربرد RFID برای دسترسی به یک سایت امن، با کد زیر مشخص میشود که کدام کارتهای بدون تماس معتبر یا غیرمعتبر هستند و براین اساس یک LED سبز یا قرمز روشن میشود. هنگام شبیهسازی استفاده از RFID در یک طرح امنیتی، بجای روشن کردن یک LED، میتوان روتور یک سروو موتور را برای باز کردن یک قفل چرخاند. این طرح از دو تابع ()cardID و ()cardResult برای خواندن UID کارت از بافر با یک کاراکتر بطورهمزمان و چاپ روی مانیتور سریال در صورت معتبر یا نامعتبر بودن کارت استفاده میکند. همانند لیست کد زیر، بسیاری از لیست دستورات متغیرها را اعلام و در مانیتور سریال چاپ میکنند. جزییات دستورات کتابخانه MFRC522، همانند mfrc522.PICC_GetType(mfrc522.uid.sak) از MFRC522>Examples در کتابخانه MFRC522 درون IDE آردوینو بدست میآیند.
#include // include SPI library
#include // include MFRC522 library
int RSTpin = 9; // reset pin for MFRC522
int SDApin = 10; // serial data pin
MFRC522 mfrc522(SDApin, RSTpin); // associate mfrc522 with MFRC522 library
int redLED = 4; // red LED pin
int greenLED = 3; // green LED pin
int nuid = 1; // number of valid cards
String uids[20]; // list of valid UIDs – maximum 20
String uid;
int cardOK, pin, piccType;
int cardRead; // ** for add/delete card Listing 11-3
void setup()
{
Serial.begin(9600); // define Serial output baud rate
SPI.begin(); // initialise SPI bus
mfrc522.PCD_Init(); // initialise MFRC522
pinMode (redLED, OUTPUT); // define LED pins as output
pinMode (greenLED, OUTPUT);
uids[0] = "c049275"; // UIDs of valid cards
}
void loop()
{
if(!mfrc522.PICC_IsNewCardPresent()>0) return; // wait for a new card
if(!mfrc522.PICC_ReadCardSerial()>0) return; // read new card content
cardID(mfrc522.uid.uidByte, mfrc522.uid.size); // function to
// read card UID
Serial.print("\nCard UID\t"); // print "card UID" and a tab
Serial.println(uid); // print card UID
piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); // card PICC type
Serial.print("PICC type\t"); // print PICC type
Serial.println(mfrc522.PICC_GetTypeName(piccType)); // card SAK code
Serial.print("SAK code\t"); // print "SAK code" and a tab
Serial.println(mfrc522.uid.sak); // print SAK HEX code
cardOK = 0;
pin = redLED;
for (int i=0; i
اعتبارسنجی مستر کارت
در یک سامانه امنیتی کارتی بدون تماس، کارتهای جدید باید بهعنوان کارتهای معتبر و کارتهای قدیمی بهعنوان کارتهای نامعتبر طبقهبندی شوند. به منظور بهروزرسانی لیست کارتهای معتبر لیست کد زیر به لیست کد بالا افزوده میشود. یک مستر کارت برای اعتبارسنجی یک کارت یا حذف یک کارت از مجموعه کارتهای معتبر بکاربرده میشود. مستر کارت اولین کارت در آرایه []uid است. پس از شناسایی مستر کارت، وجود UID کارت بعدی خواندهشده در لیست کارتهای معتبر بررسی میشود، اگر در حال حاضر در لیست وجود نداشته باشد به این لیست افزوده میشود، یا اگر در حال حاضر در این لیست وجود داشته باشد از لیست پاک میشود. مجموعه دستورات لیست زیر بهصورت یک خط ماقبل آخر تابع ()void loop به کد بالا اضافه میشود. تابعی دیگر، ()readUID در لیست کد بعدی، برای تعیین وضعیت خوانده شدن کارت به انتهای لیست دستورات افزوده میشود.
دو دستور اول در تابع ()readUID مشابه دو دستور اول در تابع ()void loop هستند با یک 0 که پس از return اضافه شده است (لیست کد زیر را نگاه کنید). اگر کارتی به کارتخوان ارائه نشده یا خوانده نشده باشد، تابع () readUID صفر را برمیگرداند. پس از خوانده شدن کارت، تابع () readUID یک را برمیگرداند. علامت ! قبل از یک متغیر در تابع () readUID مقدار مخالف یعنی 0 و 1 یا LOW و HIGH را نشان میدهد. دستور if(!mfrc522.PICC_IsNewCardPresent()>0) معادل دستور if(mfrc522.PICC_IsNewCardPresent()<1) است.
int readUID()
{
if(!mfrc522.PICC_IsNewCardPresent()>0) return 0; // wait for a new card
if(!mfrc522.PICC_ReadCardSerial()>0) return 0; // read card content
return 1;
}
if(uid == uids[0]) // read card is the master card
{
Serial.println("\nMaster card"); // print "Master card" on a new line
digitalWrite(redLED, HIGH); // turn on the red and green LEDs
digitalWrite(greenLED, HIGH);
delay(1000);
digitalWrite(redLED, LOW); // turn off the red and green LEDS
digitalWrite(greenLED, LOW);
Serial.println("Scan card to be deleted or added"); // print message
int cardRead=0;
while(!cardRead >0) // wait for a card to be read
{
cardRead = readUID(); // function to detect card
if(cardRead == 1) // card detected
{
cardID(mfrc522.uid.uidByte, mfrc522.uid.size); // read card UID
cardOK = 0;
for (int i=0; i
خواندن و نوشتن بر روی یک کارت کلاسیک مایفر 1 کیلوبایتی
کارتخوان MFRC522 RFID با یک فرآیند اعتبارسنجی مسترکارت برای شبیهسازی یک سیستم امنیتی با افزودن و حذف کردن کارتهای بدون تماس از یک لیست اعتبارسنجی، برای خواندن و نوشتن بر روی کارتهای بدون تماس MIFARE بکاربرده میشود.
کارت خوان MFRC522 برای نوشتن بر روی یک کارت MIFARE کلاسیک 1 کیلوبایتی یا تگ نیز بکاربرده میشود. چهارمین بلوک یک سکتور تریلر سکتور است که شامل کلیدهای دسترسی و امنیتی است و نباید بیش از حد بر روی آن نوشته شود. سه بخش اول در یک سکتور برای ذخیره داده هستند، به استثنای اولین بلوک اولین سکتور که اطلاعات سازنده را دربرمیگیرد.
دستورات لیست زیر، دادهها را بر روی یک بلوک وارد شده توسط کاربر مینویسند و سپس محتوای بلوکهای ذخیرهسازی اطلاعات را نمایش میدهند. بازهم، بخش اعظم دستورات برای معرفی متغیرها و چاپ آنها بر روی مانیتور سریال است. در این دستورات، متن ABCDEFGHIJKLMNOP بر روی بلوک موردنظر که در byte blockData[16] تعریفشده نوشته میشود و تنظیم blockData[16] در {00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,} بلوک را به مقدار null پیش فرض بازمیگرداند.
در تابع ()void loop، توابع ()while برای انتظار تا ارائه یک کارت و ورود یک شماره بلوک به مانیتور سریال بکاربرده میشوند. با توجه به اینکه در حین انتظار هیچ اقدامی لازم نیست، همانطور که در دستور while (Serial.available () == 0) {} نشان داده شده است هیچ دستوری در توابع ()while وجود ندارد. دستور ()block= Serial.parseInt شماره بلوک را از بافر سریال بیرون میکشد. پس از وارد کردن یک شماره بلوک، برای اطمینان از اینکه بلوک تریلر سکتور نباشد شماره بلوک بررسی میشود. سپس اطلاعات موجود در blockData با استفاده از تابع writeBlock(block, blockData) در بلوک موردنظر نوشته میشوند. سپس برای هر بلوک، محتوای داده کارت بدون تماس با استفاده از تابع readBlock(block, blockRead) خوانده شده و بر روی مانیتور سریال نمایش داده میشود.
در پایان، ارتباط با کارت بدون تماس با دستور ()mfrc522.PCD_StopCrypto1 بسته میشود. دو تابع () readBlock و ()writeBlock ساختار مشابهی دارند. قبل از خواندن یا نوشتن بر روی یک بلوک اعتبارسنجیها با تابع ()mfrc522.PCD_Authenticate انجام شده و نتیجه بررسی با MFRC522::STATUS_OK برگردانده میشود. تابع ()readBlock داده هر بلوک، بجز چهارمین بلوک در هر سکتور که تریلر سکتور و شامل کلیدهای دسترسی و امنیتی است، را میخواند. دستور mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid),&key,sector) همزمان با mfrc522 تمامی اطلاعات درون یک سکتور مشخص را خوانده و بر روی مانیتور سریال نمایش میدهد. دستور PICC_DumpToSerial(&(mfrc522.uid)) تمامی دادهها برروی کارت کلاسیک MIFARE یک کیلوبایتی یا کارت بدون تماس RFID 4 کیلوبایتی را بر روی مانیتور سریال نمایش میدهد.
#include // include SPI library
#include // include MFRC522 library
int RSTpin = 9; // reset pin for MFRC522
int SDApin = 10; // serial data pin
MFRC522 mfrc522(SDApin, RSTpin); // associate mfrc522 with MFRC522 library
MFRC522::MIFARE_Key key; // access key
byte blockData[16] = {"ABCDEFGHIJKLMNOP"}; // data to be written
// reset block to default value
//byte blockData[16] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte blockRead[18]; // to hold the read data
byte blocksz = sizeof(blockRead);
int block, sectorTrail, check;
void setup()
{
Serial.begin(9600); // define Serial output baud rate
SPI.begin(); // initialise SPI bus
mfrc522.PCD_Init(); // initialise mfrc522
for (byte i=0; i<6; i++) key.keyByte[i] = 0xFF; // access key set to HEX 0xFF
}
void loop()
{ // print message to Serial Monitor
Serial.println("Place card or tag beside MFRC522 reader");
while (!mfrc522.PICC_IsNewCardPresent())
{}; // do nothing but wait for a new card
mfrc522.PICC_ReadCardSerial(); // read card content
Serial.println("Enter block number"); // print message
while(Serial.available() == 0){} // no action until entry in serial buffer
while(Serial.available() >0) block = Serial.parseInt(); // get block number
if((block+1)%4==0 || block == 0) // check if block is sector trailer block
{ // print message to
Serial.print("Cannot write to block "); // Serial Monitor
Serial.println(block); // return to start of void loop()
return;
}
writeBlock(block, blockData); // function to write data
Serial.print("\nFinished writing to block "); // print message
Serial.println(block);
for (block=0; block<64; block++) // display content of non-sector
{ // trailer blocks
if((block+1) % 4 !=0 && block !=0) // non-sector trailer blocks
{
readBlock(block, blockRead); // function to read data
Serial.print("\nBlock "); // print block number
Serial.print(block);Serial.print("\t");
for (int i=0 ; i<16 ; i++) Serial.write(blockRead[i]);
} // print block data
}
Serial.println("\n\nFinished rea ding blocks"); // print message
Serial.println("Enter 1 to continue writing to a card or tag");
while(Serial.available() == 0) { } // no action until entry to serial buffer
// extract integer from serial buffer
while(Serial.available()>0) check=Serial.parseInt();
mfrc522.PCD_StopCrypto1(); // stop communication to card or tag
}
void writeBlock (int block, byte blockData[]) // function to write to block
{
sectorTrail = 3+4*(block/4);
check = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,
sectorTrail, &key, &(mfrc522.uid));
if (check != MFRC522::STATUS_OK)
Serial.println(mfrc522.GetStatusCodeName(check));
check = mfrc522.MIFARE_Write(block, blockData, 16);
if (check != MFRC522::STATUS_OK)
Serial.println(mfrc522.GetStatusCodeName(check));
}
void readBlock (int block, byte blockRead[]) // function to read block
{
sectorTrail = 3+4*(block/4);
check = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,
sectorTrail, &key, &(mfrc522.uid));
if (check != MFRC522::STATUS_OK)
Serial.println(mfrc522.GetStatusCodeName(check));
check = mfrc522.MIFARE_Read(block, blockRead, &blocksz);
if (check != MFRC522::STATUS_OK)
Serial.println(mfrc522.GetStatusCodeName(check));
}