-
Notifications
You must be signed in to change notification settings - Fork 1.4k
How to change keys?
Rotzbua edited this page Mar 24, 2019
·
3 revisions
Mifare Classics use 2 different keys to manage the access to the content of a block. They can be changed to a custom key.
Know your keys otherwise you could not access the block anymore.
/**
----------------------------------------------------------------------------
This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
for further details and other examples.
NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
Released into the public domain.
----------------------------------------------------------------------------
This sample shows how to change KeyA or KeyB on a MIFARE Classic PICC
(= card/tag).
BEWARE: Data will be written to the PICC, in sector #15 (blocks #60 to #63).
Typical pin layout used:
-----------------------------------------------------------------------------------------
MFRC522 Arduino Arduino Arduino Arduino Arduino
Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
Signal Pin Pin Pin Pin Pin Pin
-----------------------------------------------------------------------------------------
RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
SPI SS SDA(SS) 10 53 D10 10 10
SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
*/
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
MFRC522::MIFARE_Key key;
// MFRC522::MIFARE_Key keyB;
MFRC522::MIFARE_Key newKeyA = {keyByte: {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}};
MFRC522::MIFARE_Key newKeyB = {keyByte: {0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5}};
/**
Initialize.
*/
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
// Prepare the key
// using FFFFFFFFFFFFh which is the default at chip delivery from the factory
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
key.keyByte[i] = 0xFF;
// keyB.keyByte[i] = 0xFF;
}
Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
Serial.print(F("Using key (for A and B):"));
dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
Serial.println();
}
/**
Main loop.
*/
void loop() {
// Look for new cards
if (!mfrc522.PICC_IsNewCardPresent())
return;
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial())
return;
// Show some details of the PICC (that is: the tag/card)
Serial.print(F("Card UID:"));
dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
Serial.println();
Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.println(mfrc522.PICC_GetTypeName(piccType));
// Check for compatibility
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI
&& piccType != MFRC522::PICC_TYPE_MIFARE_1K
&& piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
Serial.println(F("This sample only works with MIFARE Classic cards."));
return;
}
// change keys in section 15 block 63
if (!MIFARE_SetKeys(&key, &key, &newKeyA, &newKeyB, 15)) {
return;
}
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
/**
Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte* buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
bool MIFARE_SetKeys(MFRC522::MIFARE_Key* oldKeyA, MFRC522::MIFARE_Key* oldKeyB,
MFRC522::MIFARE_Key* newKeyA, MFRC522::MIFARE_Key* newKeyB,
int sector) {
MFRC522::StatusCode status;
byte trailerBlock = sector * 4 + 3;
byte buffer[18];
byte size = sizeof(buffer);
// Authenticate using key A
Serial.println(F("Authenticating using key A..."));
status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, oldKeyA, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return false;
}
// Show the whole sector as it currently is
Serial.println(F("Current data in sector:"));
mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), oldKeyA, sector);
Serial.println();
// Read data from the block
Serial.print(F("Reading data from block ")); Serial.print(trailerBlock);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return false;
}
Serial.print(F("Data in block ")); Serial.print(trailerBlock); Serial.println(F(":"));
dump_byte_array(buffer, 16); Serial.println();
Serial.println();
// Authenticate using key B
Serial.println(F("Authenticating again using key B..."));
status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, oldKeyB, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return false;
}
if (newKeyA != nullptr || newKeyB != nullptr) {
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
if (newKeyA != nullptr) {
buffer[i] = newKeyA->keyByte[i];
}
if (newKeyB != nullptr) {
buffer[i+10] = newKeyB->keyByte[i];
}
}
}
// Write data to the block
Serial.print(F("Writing data into block ")); Serial.print(trailerBlock);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(trailerBlock, buffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return false;
}
Serial.println();
// Read data from the block (again, should now be what we have written)
Serial.print(F("Reading data from block ")); Serial.print(trailerBlock);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(trailerBlock, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.print(F("Data in block ")); Serial.print(trailerBlock); Serial.println(F(":"));
dump_byte_array(buffer, 16); Serial.println();
return true;
}