NFC RC522 - Смена ключа на карте
- Войдите на сайт для отправки комментариев
Ср, 27/07/2016 - 09:51
Друзья, добрый день!
Кто имел опыт общения с RC522, подскажите, как поставить кастомный ключ на карту Mifare при её записи?
На всякий случай прикладываю код - смысл устройства в включении реле при прикладывании карты, при этом карта действует только определенное время. Собственно, хочется чтобы карту нельзя было просто клонировать, воспользовавшись заводским ключом.
int deviceGroup = 16; int masterGroup = 17; long maxtime = 60; #define RST_PIN 9 //Настраиваемый пин #define SS_PIN 10 //Настраиваемый пин #include <SPI.h> #include <MFRC522.h> byte bufferATQA[10]; byte bufferSize = sizeof(bufferATQA); int cardGroup = 0; long cardTime = 0; int masterwaiting = 0; boolean mastertick = false; byte sector = 1; byte valueBlockTime = 5; byte valueBlockGroup = 6; byte trailerBlock = 7; byte buffer[18]; byte size = sizeof(buffer); long value; MFRC522::StatusCode status; MFRC522 mfrc522(SS_PIN, RST_PIN); // Создаем объект MFRC522. MFRC522::MIFARE_Key key; void setup() { Serial.begin(9600); while (!Serial); SPI.begin(); mfrc522.PCD_Init(); // Ключ для карты (один и тот же ключ A и B) // Использовать FFFFFFFFFFFF для заводских настроек карт for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } Serial.println(F("Welcome to card reader!")); //включаем порты светодиодов pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); } void loop() { delay(1000); if (masterwaiting) { IndicationMaster(); masterwaiting = masterwaiting - 1; } if ( !rfid_wait_card() || !rfid_authenficate() ) { Relay(false); return; } formatValueBlock(valueBlockGroup); formatValueBlock(valueBlockTime); //проверки на каждое действие по воздуху cardGroup = rfid_readBlock(valueBlockGroup); cardTime = rfid_readBlock(valueBlockTime); if (cardGroup < 0 || cardTime < 0) { Relay(false); rfid_stop(); return; } Serial.print(F("Card Group = ")); Serial.println(cardGroup); Serial.print(F("Card Time = ")); Serial.println(cardTime); if (!masterwaiting) { //проверяем время и группу на соответствие if (cardGroup != deviceGroup || cardTime < 1) { Serial.println("Time or group wrong!"); Relay(false); } //если группа карты соответствует группе устройства и время больше нуля if (cardGroup == deviceGroup && cardTime > 0) { //записываем уменьшенное время на карту cardTime = cardTime - 1; if (!rfid_writeBlock(valueBlockTime, cardTime)) { rfid_stop(); return; } //отображаем время карты и включаем реле Indication(cardTime*100/maxtime); Relay(true); } //если прислонена мастеркарта if (cardGroup == masterGroup) { //включаем режим ожидания карты для перезаписи IndicationMaster(); //и ставим счетчик ожидания на десять секунд masterwaiting = 10; } } else { //если ждём карту для перезаписи //только если прислонена не мастеркарта if (cardGroup != masterGroup) { //записываем максимальное время и номер девайса if (!rfid_writeBlock(valueBlockTime, maxtime)) { rfid_stop(); return; } if (!rfid_writeBlock(valueBlockGroup, deviceGroup)) { rfid_stop(); return; } //моргаем светодиодами, сигнализируя о успешной записи IndicationMasterWritten(); masterwaiting = false; } } //заканчиваем работу с картой rfid_stop(); } /* ФУНКЦИИ */ boolean rfid_wait_card() { // если нет новой карты, то пытаемся разбудить текущую if ( ! mfrc522.PICC_IsNewCardPresent()) { mfrc522.PICC_WakeupA(bufferATQA, &bufferSize); } // если нет карты - отключить реге if ( ! mfrc522.PICC_ReadCardSerial()) { return false; } // проверяем карту на совместимость MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType != MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K) { return false; } return true; } boolean rfid_authenficate() { // аутенфикация status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { return false; } byte trailerBuffer[] = { 255, 255, 255, 255, 255, 255, // Keep default key A 0, 0, 0, 0, 255, 255, 255, 255, 255, 255}; // Keep default key B mfrc522.MIFARE_SetAccessBits(&trailerBuffer[6], 0, 6, 6, 3); // Read the sector trailer as it is currently stored on the PICC status = mfrc522.MIFARE_Read(trailerBlock, buffer, &size); if (status != MFRC522::STATUS_OK) { return false; } // Check if it matches the desired access pattern already; // because if it does, we don't need to write it again... if ( buffer[6] != trailerBuffer[6] && buffer[7] != trailerBuffer[7] && buffer[8] != trailerBuffer[8]) { // They don't match (yet), so write it to the PICC status = mfrc522.MIFARE_Write(trailerBlock, trailerBuffer, 16); if (status != MFRC522::STATUS_OK) { return false; } } // Authenticate using key B status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { return false; } return true; } void rfid_stop() { // Halt PICC mfrc522.PICC_HaltA(); // Stop encryption on PCD mfrc522.PCD_StopCrypto1(); } void formatValueBlock(byte blockAddr) { byte buffer[18]; byte size = sizeof(buffer); MFRC522::StatusCode status; status = mfrc522.MIFARE_Read(blockAddr, buffer, &size); if (status != MFRC522::STATUS_OK) { return; } if ( (buffer[0] != (byte)~buffer[4]) && (buffer[1] != (byte)~buffer[5]) && (buffer[2] != (byte)~buffer[6]) && (buffer[3] != (byte)~buffer[7]) && (buffer[0] != buffer[8]) && (buffer[1] != buffer[9]) && (buffer[2] != buffer[10]) && (buffer[3] != buffer[11]) && (buffer[12] != (byte)~buffer[13]) && (buffer[12] != buffer[14]) && (buffer[12] != (byte)~buffer[15])) { byte valueBlock[] = { 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, blockAddr, ~blockAddr, blockAddr, ~blockAddr }; status = mfrc522.MIFARE_Write(blockAddr, valueBlock, 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("MIFARE_Write() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); } } } void Relay(boolean status) { if (status) { Serial.println(F("Relay opened.")); digitalWrite(7, HIGH); } else { Serial.println(F("Relay closed.")); digitalWrite(7, LOW); if (!masterwaiting) { Indication(0); } } } void Indication(int percentage) { if (percentage > 90) { PORTD = B01111000; return; } if (percentage >50) { PORTD = B00111000; return; } if (percentage >25) { PORTD = B00011000; return; } if (percentage > 0) { PORTD = B00001000; return; } PORTD = B00000000; return; } void IndicationMaster() { Serial.println("Master card!"); if (mastertick) { mastertick = false; PORTD = B01001000; } else { mastertick = true; PORTD = B00110000; } } void IndicationMasterWritten() { delay(250); PORTD = B01000000; delay(250); PORTD = B00100000; delay(250); PORTD = B00010000; delay(250); PORTD = B00001000; delay(250); PORTD = B00000000; } long rfid_readBlock(byte valueBlockNumber) { status = mfrc522.MIFARE_GetValue(valueBlockNumber, &value); if (status != MFRC522::STATUS_OK) { Serial.print(F("mifare_GetValue() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return 0; } return value; } boolean rfid_writeBlock(byte valueBlockNumber, long valueToSet) { status = mfrc522.MIFARE_SetValue(valueBlockNumber, valueToSet); if (status != MFRC522::STATUS_OK) { Serial.print(F("mifare_SetValue() failed: ")); Serial.println(mfrc522.GetStatusCodeName(status)); return false; } return true; }