Beperking van de toegang tot apparaten via contactloze kaart met de NodeMCU en de RC522 Module Deel 4 - Down the Rabbit Hole

Blog van vandaag gaat " down the Rabbit Hole" zoals beloofd en we omgaan met de internals van de MiFare Proximity Integrated Contactloze kaarten (ANP) Nummer. We kijken naar de details en nemen een kijkje op de functies.

Veel Kaartlezer- Projecten waarmee mf522 chipset wordt gebruikt als basis voor de Arduino die ik persoonlijk al heb gezien, helaas noch in de beveiligingstechnologie, noch in mogelijkheden gebruik maken van wat de Mifare Classic kaart biedt ons in functies.

Deze projecten zijn beperkt tot het lezen van de unieke ID (UUID) van de kaart, die vrij kan worden gelezen voor elke kaartlezer en mobiele telefoon, en om het te controleren tegen een lijst van toegestane UUID's. Als deze in de lijst is opgenomen, wordt de kaart als geldig beschouwd.

Ook in onze vorige delen we maken gebruik van dit principe. We willen dit veranderen met onze blog vermelding vandaag en sla gegevens veilig op onze MiFare Classic kaart.

Vanwege het kaarttype "MiFare Classic" dat in dit project wordt gebruikt (let ook op deze notitie), kunnen we onze eigen informatie van de kaart opslaan en beschermen tegen onbevoegd lezen of wijzigen.

Hiervoor heeft de fabrikant al 16 sectoren (0-15) met elk 4 * 16 bytes, met uitzondering van sector 0 , 3 * 16 bytes vrij kunnen worden beschreven. 16 bytes van elke sector worden sectortrailers genoemd en gebruikt om de 2 sectorsleutels te deponeren en de toegangsmatrix te definiëren.

De 16 bytes van een sector trailer zijn als volgt verdeeld:
6 bytes - eerste sectorsleutel
6 bytes - tweede sectorsleutel
4 bytes - definitie van toegangsmachtigingen

We willen nu de voor- en achternaam van ons versleuteld op onze kaart opslaan. Om dit te doen, definiëren we een sector (1-15) via de constante ... die we hiervoor willen gebruiken. Ik koos sectorblok 1 in de code.

De voornaam moet zich in het tweede veld van 16 bytes en de achternaam in het derde veld van 16 bytes bevindt. Het eerste veld van 16 bytes is gereserveerd voor toekomstige extensies.

We hebben ook een belangrijke definitie nodig, die we opslaan in de MiFareClassicKeyTable-structuur.

Wijzig dit blok (2x 6 bytes) met uw eigen sleutelmateriaal tijdens de replica en sla het op een veilige plaats op, anders zal iedereen die dit project kent met het sleutelmateriaal dat in de code in platte tekst wordt vermeld uw kaart lezen en uw eigen geldig lezen! kan kaarten maken voor uw apparaatbediening.

Kleine spoiler: We zullen dit sleutelmateriaal ook weer nodig hebben in een latere voortzetting van de serie. Houd er rekening mee dat u de kaart beschrijft en de beveiligingsopties wijzigt. Als gevolg hiervan is de kaart mogelijk niet meer bruikbaar voor andere doeleinden!

Nadat we het sleutelmateriaal hebben gewijzigd, uploaden we de volgende code naar ons ESP:

 

#include <Spi.H>
#include <MFRC522.H>
#include <ESP8266WiFi.H>
#include <WiFiClient.h> 
#include <ESP8266WebServer.H>
#include <ESP8266mDNS.H>
#include <Eeprom.H>
#include <Fs.H>           Neem de SPIFFS-bibliotheek op

#define RST_PIN     5     SPI Reset-pin (D1-uitvoer)
#define RELAIS_PIN  16    Relais (D0-uitgang) [LOW Active] - Ook interne LED in de buurt van USB-poort
#define SS_PIN      15    SPI Slave Select Pin

#define RGBLED_R    2     Rood (D4-uitvoer) 
#define RGBLED_G    0     Groen (D3 output) - Ook interne LED op de ESP module
#define RGBLED_B    4     Blauw (D2-uitvoer)

#define WiFiPwdLen WiFiPwdLen   25   Maximale WiFi-wachtwoordlengte
#define STANameLen STANamelen 20     Maximale WiFi SSID lengte
#define ESPHostNamelen 20 Maximum aantal tekens ESPHostName

#define Keya Waar         PICC-vlagdefinitie
#define Keyb Keyb Valse        PICC-vlagdefinitie

#define LED_BUILTIN 16
#define PIN_WIRE_SDA 4 
#define PIN_WIRE_SCL 5 

#define USED_Sector 1  Kaartsector gebruikt voor authenticatie- en configuratiegegevens (geldig: 1- 15)

ADC_MODE(ADC_TOUT);   Configureer analoge invoer A0 naar extern. ADC_TOUT (voor externe spanning), ADC_VCC (voor systeemspanning). 
MFRC522 mfrc522(SS_PIN, RST_PIN);   Instantie van MFRC522 maken
MFRC522::MIFARE_Key Sleutel;
ESP8266WebServer Server(80);        Instantie maken van webservers

Struct WiFieeprom   {     Char ESPHostName[ESPHostNamelen];      Char APSTAName[STANameLen STANamelen]; STATION Naam om connect, indien ontopgericht        Char WiFiPwd WiFiPwd[WiFiPwdLen WiFiPwdLen]; WiFiPAszwaard, indien definded         Char ConfigValid (ConfigValid)[3]; Als Config Vaild is, is tag "TK" vereist"   };    Struct MifareClassicKeyTable   {    Byte Key_A[6] = {0x22,0x44,0xFA 0xFA,0xAB 0xAB,0x90,0x11};   Sleutel voor PICC-kaart u wijzigen.     Byte Key_B[6] = {0xFE,0xE1,0xAA,0x3D,0xDF,0x37};   Sleutel voor PICC-kaart u wijzigen.     Char ConfigValid (ConfigValid)[3]; Als Config Vaild is, is tag "TK" vereist"   };    MifareClassicKeyTable MifareClassicKey;
WiFieeprom MyWiFiConfig MyWiFiConfig;

Wereldwijd gebruikte variabelen
Bool Resultaat  = Valse;
Bool LearnNewCard = Valse;
Bool EraseCard = Valse; 
Bool ExpirdateActive = Valse;
Tekenreeks Achternaam;
Tekenreeks Givenname;
Tekenreeks Vervaldatum;
Tekenreeks Temp;
Unsigned Lange Sessionid;
Unsigned Lange PCD_ServiceCall_Handler = 0;
Unsigned Lange PCD_WatchDog_Handler = 0;
uint8_t Gegevensbuffer[18]  = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };


Void Setup()     {    pinMode(RST_PIN,Output);   digitalWrite(RST_PIN,Hoge);   pinMode(RELAIS_PIN,Output);   pinMode(RGBLED_R,Output);   pinMode(RGBLED_G,Output);   pinMode(RGBLED_B,Output);   digitalWrite(RELAIS_PIN,Hoge);    Relais inactief   SetRGBLed(255,0,255,Valse);       Led Color Purple Initalization Begin   Seriële.Beginnen(115200);               Serial communicatie met de pc initialiseren met 115200 Baud   Seriële.println("");   Temp = "ATSN:"+ Tekenreeks(Ihb.getChipId());   Seriële.println(Temp);   Serial.print("ADC-waarde:"); Serial.println(analogRead(A0));   Spi.Beginnen();                      Spi-communicatie initialiseren   PCDHardReset();   Sessionid = millis();    Resultaat  = startWiFiClient startWiFiClient();     InitalizeHTTPServer();   SetRGBLed(0,0,255,Valse);       Led Color Blue Initalization voltooid   ESP.wdtEnable(WDTO_4S);              Watchdog starten   }


Start Helper/ Optimalisatiefuncties **********************************************************************************************************************************************************************************************************************************************************************************************************************************************************

Void SetRGBLed(Byte RedValue RedValue,Byte Groene waarde,Byte BlueValue,Booleaanse SlowFade)  Funkion voor het regelen van de RGB Led
{   digitalWrite(RGBLED_R,Lage);       digitalWrite(RGBLED_G,Lage);   digitalWrite(RGBLED_B,Lage);    Als (RedValue RedValue == 255)   { digitalWrite(RGBLED_R,Hoge); }      Als (Groene waarde == 255) { digitalWrite(RGBLED_G,Hoge); }   Als (BlueValue == 255)  { digitalWrite(RGBLED_B,Hoge); }    }

Stop Helper/ Optimalisatiefuncties *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

Start Functions Webserver **********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

Cookie base routines zijn gebaseerd op GIT fragment:
//https://github.com/esp8266/ESPWebServer/blob/master/examples/SimpleAuthentification/SimpleAuthentification.ino
Bool is_authentified()
{     Als (Server.Hasheader("Cookie")){       Cookie gevonden      Temp = Server.Header("Cookie");       Serial.println(temp);      Tekenreeks SessionStr SessionStr = Tekenreeks(Ihb.getChipId()) + "=" + Tekenreeks(Sessionid);      Opbrengst();      Als (Temp.Indexof(SessionStr SessionStr) != -1) {         Webverificatie geslaagd        Temp = "";        Terug Waar;       }     }        Webverificatie is mislukt    Temp = "";    Sessionid = millis();    Terug Valse; 
} 

Void handleLogin(){   Tekenreeks Msg;   Tekenreekscookie = server.header("Cookie");   Serial.println(cookie);   Als (Server.hasArg hasArg("LOSKOPPELEN")){     Verbinding gebruiker ontkoppelen;     Server.sendHeader("Locatie","/login");     Server.sendHeader("Cache-Control","no-cache");     Sessionid = millis();     Temp = Tekenreeks(Ihb.getChipId()) + "= NA ; HttpOnly ; SameSite=Strict";     Server.sendHeader("Stel cookie",Temp);     Temp = "";     Server.Verzenden(301);     Opbrengst();     Terug;   }   Als (Server.hasArg hasArg("GEBRUIKERSNAAM") && Server.hasArg hasArg("WACHTWOORD")){     Temp = Tekenreeks(Ihb.getChipId());     Als (Server.Slechte("GEBRUIKERSNAAM") == "Admin" &&  Server.Slechte("WACHTWOORD") == Temp ){       Server.sendHeader("Locatie","/");       Server.sendHeader("Cache-Control","no-cache");       Sessionid = millis();       Temp = Tekenreeks(Ihb.getChipId()) + "=" + Tekenreeks(Sessionid) + "; HttpOnly ; SameSite=Strict";       Server.sendHeader("Stel cookie",Temp);       Temp = "";       Server.Verzenden(301);       Opbrengst();       Terug;     }   Msg = "<script>alert('Verkeerde gebruikersnaam of wachtwoord !'); </script>";   }    CSS_Header_Template();    Opbrengst();    Temp = "<head><title>Login</title><head><body><DIV ALIGN=CENTER>";    Server.sendContent(Temp);    Temp = "<h2>Registratie bij kaartlezer RC522</h2><body><br><br><br>table border=0 bgcolor=black><<tr><th><DIV ALIGN=RIGHT>";    Server.sendContent(Temp);    Temp = "<formulieractie='/login'-methode='post'>Gebruikersnaam: <invoertype=tekst Naam='GEBRUIKERSNAAM' Grootte=17 vereist><br>";    Server.sendContent(Temp);    Temp = "Wachtwoord: <input type=password Name='PASSWORD' Size=17 required><br><br><<br><br><button type=submit' ";    Server.sendContent(Temp);    Temp = "naam='Login_Button' value='1' style='hoogte: 30px; breedte: 100px' >Login</button><br></th></tr></form></DIV></table>";    Server.sendContent(Temp);    Temp = "<br><SMALL>Om in te loggen moet cookies voor deze website worden toegestaan.</SMALL>";      Server.sendContent(Temp);    Temp = Msg + "</DIV></body></HTML>";    Server.sendContent(Temp);    Temp = "";
}

Void handleNotFound()    {   Sessionid = millis();   Temp = "Pagina niet gevonden.;   Temp += "URI: ";   Temp += Server.Uri();   Temp += "AnMethod: ";   Temp += (Server.Methode() == HTTP_GET)?"GET":"POST";   Temp += "AnArguments: ";   Temp += Server.Args();   Temp += "Een";   Voor (uint8_t I.=0; I.<Server.Args(); I.++){     Temp += " " + Server.argName(I.) + ": " + Server.Slechte(I.) + "Een";   }   Opbrengst();   Server.Verzenden(404, "tekst/vlakte", Temp);   Temp = "";   }



Void handleErasePICC()
{   Als (!is_authentified())     {     Server.sendHeader("Locatie","/login");     Server.sendHeader("Cache-Control","no-cache");     Server.Verzenden(301);     Opbrengst();     Terug;     }     CSS_Header_Template();   Opbrengst();   Temp = "<head><title>Kaartlezer RC522</title><head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "<script>alert('Houd de kaart nu voor de lezer verwijderd!'); </script>";      Server.sendContent(Temp);    Opbrengst();   SetRGBLed(0,255,255,Valse);       Led-kleurcyaanprogrammeermodus   EraseCard = Waar;         Temp = "</body></html>";   Server.sendContent(Temp);   Server.Client().Stoppen();   Temp = "";
}


Void handleNewPICC()
{   Als (!is_authentified())     {     Server.sendHeader("Locatie","/login");     Server.sendHeader("Cache-Control","no-cache");     Server.Verzenden(301);     Terug;     }   Als (Server.hasArg hasArg("Achternaam") && Server.hasArg hasArg("Givenname"))   {      Achternaam = Server.Slechte("Achternaam");     Givenname = Server.Slechte("Givenname");     Vervaldatum = Server.Slechte("ExpDate");     Als (Server.hasArg hasArg("ExpDateOption")) { ExpirdateActive = Waar; } Anders { ExpirdateActive = Valse; }     Temp = "<script>alert('Houd de nieuwe kaart nu voor de lezer!'); </script>";        Server.sendContent(Temp);      SetRGBLed(255,255,0,Valse);       Led-kleur gele programmeermodus     LearnNewCard = Waar;     Opbrengst();     Terug;       }         CSS_Header_Template();   Opbrengst();   Temp = "<head><title>Kartenleser RC522</title><head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "";   Temp = "<br><br><br><br><table border=0 ALIGN=CENTER><th>";   Server.sendContent(Temp);   Temp = "<table border=1 bgcolor = black><form action='/newPICC' method='post'>";   Server.sendContent(Temp);   Temp = "<tr><th>Karteninhaber:<br><div ALIGN=RIGHT>";   Server.sendContent(Temp);   Temp = "Vorname: <input type=text Name='Surname' Size=17 maxlenght=16 placeholder='Max' required><br>";   Server.sendContent(Temp);   Temp = "Nachname: <input type=text Name='Givenname' Size=17 maxlenght=16 placeholder='Mustermann' required><br>";   Server.sendContent(Temp);   Temp = "</div></th><th>Kartenmetadaten:<br><DIV ALIGN=RIGHT>";   Server.sendContent(Temp);       Temp = "<input Name='ExpDateOption' TYPE=checkbox WAARDE=1 >Ablaufdatum:<invoertype=datum Naam='ExpDate' Grootte = 17 >";   Server.sendContent(Temp);   Temp = "<br><th><tr><th></table><br>";   Server.sendContent(Temp);   Temp = "<button type='submit' name='NewCard' value='1' style='height: 30px; breedte: 200px' >Neue Smartcard erstellen</button>";   Server.sendContent(Temp);   Temp = "<br></form></tr></th></table>";   Server.sendContent(Temp);   Temp = "</body></html>";   Server.sendContent(Temp);   Server.Client().Stoppen();   Opbrengst();     Temp = "";
}

Void handleRoot()
{   Als (!is_authentified()){     Server.sendHeader("Locatie","/login");     Server.sendHeader("Cache-Control","no-cache");     Server.Verzenden(301);     Terug;     }   HTML-inhoud   CSS_Header_Template();   Opbrengst();   Temp = "<head><title>Kartenleser RC522</title><head><body>";   Server.sendContent(Temp);   HtmlNavStructure();   Temp = "<div ALIGN=CENTER><br><br><br><br><BIG>Willkommen auf der Smartkartenleser RC522 Webseite.</BIG><br>";   Server.sendContent(Temp);   Temp = "Resetgrund: " + Tekenreeks(Ihb.getResetReason()) + "<br>";   Server.sendContent(Temp);   Temp = "Freier Heapspeicher: " + Tekenreeks(Ihb.getFreeHeap()) + " Bytes<br>";   Server.sendContent(Temp);   Temp = "Int. Flash: " + Tekenreeks(Ihb.getFlashChipRealSize()) + " Bytes<br>";   Server.sendContent(Temp);   Resultaat = mfrc522.PCD_PerformSelfTest();    mfrc522.PCD_Init();                       Initialisiere MFRC522 Lesemodul   mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Setzt Antenne auf max. Empfang Empfang Empfang   mfrc522.PCD_AntennaOn();    Opbrengst();   Als (Resultaat) {Temp = "RC522 PCD-Status: OK<br>"; } Anders {Temp = "RC522 PCD-Status: Fehler!<br>"; }    Server.sendContent(Temp);   Temp = "CPU-ID: " + Tekenreeks(Ihb.getChipId()) + " @ " + Tekenreeks(Ihb.getCpuFreqMHz getCpuFreqMHz()) + " MHz<br>";    Server.sendContent(Temp);   Temp = "<br>Sie sind erfolgreich angemeldet !<br><br><form action='/login' methode='get'>";   Server.sendContent(Temp);   Temp = "<button type='submit' name='DISCONNECT' value='YES' style='height: 30px; breedte: 200px' >Afmelden</button>";   Server.sendContent(Temp);   Temp = "</form></div></body></html>";   Server.sendContent(Temp);   Als (Server.hasArg hasArg("Reboot") )  Opnieuw opstarten van systeem      {     ESP.wdtFeed();             Ihb.wdtUitschakelen();     Temp = "<script>alert('Das System startet JETZT neu.'); </script>";        Server.sendContent(Temp);     Server.Client().Stoppen();     Opbrengst();     Temp = "";     Ihb.Opnieuw instellen();     Vertraging(4000);      }     Server.Client().Stoppen();   Temp = "";
}

Void CSS_Header_Template() Formatvorlage für alle internen ESP Webseiten. https://wiki.selfhtml.org/wiki/CSS   {    Server.setContentLength(CONTENT_LENGTH_UNKNOWN);    Temp = "";    Server.Verzenden (200, "tekst/html", Temp);    Temp = "<! DOCTYPE HTML PUBLIC '-/-/W3C/DTD HTML 4.01 Transitional/EN'><html lang='de'><meta charset='UTF-8'>";    Server.sendContent(Temp);    Temp = "<style type='text/css'>*{marge: 0;padding: 0;} body{background:black;color:darkorchid;font-size: 16px;" ;    server. sendContent(temp);    temp = font-family: sans-serif,arial;}. nav{width: 1300px;hoogte: 30px;marge: 0 auto;randstraal: 5px;}";    Server.sendContent(Temp);    Temp = "ul li{list-style: none;width: 200px;line-height: 60px;position: relative;background: darkorchid;" ;    server. sendContent(temp);    temp = "box-shadow: 0px 2px 5px 0px 0px grijs;tekst-align: center;float: left;background-color: #010000;} ul li ul{";    Server.sendContent(Temp);    Temp = "positie: absoluut;}. nav > ul > li:nth-of-type(1){border-radius: 5px 0px 0px 5px;}. nav > ul > li:nth-of-type(5)";    Server.sendContent(Temp);    Temp = "{border-radius: 0px 5px 5px 0px;} ul li a{kleur: rgb(182, 18, 18);width: 200px;height: 58px;display: inline-block;" ;    server. sendContent(temp);    temp = tekstdecoratie: geen;} ul li a:hover{font-weight: bold;border-bottom: 2px solid #fff;} ul li ul{display: none;}";    Server.sendContent(Temp);    Temp = ".nav ul li:hover ul{display: block;}. fa{marge-rechts: 5px;}. container{breedte: 1000px;hoogte: 200px;" ;    server. sendContent(temp);    temp = "margin: 0 auto;padding:20px 20px;} @media scherm en (maximale breedte: 480px){header{width: 100%;}";    Server.sendContent(Temp);    Temp = ".nav{display: none;width: 100%;height: auto;} ul li{breedte: 100%;float: geen;} ul li a{breedte: 100%;" ;    server. sendContent(temp);    temp = "display: block;} ul li ul{positie: statisch;} ul li ul li a{achtergrond: #222;}. fa-list.modify{display: block;}";    Server.sendContent(Temp);    Temp = ".container{breedte: 100%;hoogte: auto;} body{overflow-x:hidden;}} </stijl>";    Server.sendContent(Temp);    Temp = "";   }


Void HtmlNavStructure()   {   Temp = "<div class='menu'><nav class='nav'><ul>";   Server.sendContent(Temp);   Temp = "<li><a href='#'>System</a>";   Server.sendContent(Temp);   Temp = "<ul><li><a href='/'>Informatie</a></li>";   Server.sendContent(Temp);   Temp = "<li><a href='/? Reboot=YES'>Neustart</a></li>";   Server.sendContent(Temp);   Temp = "</ul>";   Server.sendContent(Temp);   Temp = "</li><li><a href='#'>PICC</a>";   Server.sendContent(Temp);   Temp = "<ul><li><a href='/newPICC'>Neue Karte erstellen</a></li>";   Server.sendContent(Temp);   Temp = "<li><a href='/erasePICC'>Karte löschen</a></li></ul>";   Server.sendContent(Temp);   Temp = "</li>";   temp = "</li><li><a href='#'>Ereignisprotokoll</a></li>";   Server.sendContent(Temp);   Temp = "</ul></nav></div>";   Server.sendContent(Temp);   Temp = "";   }       Void InitalizeHTTPServer()    {   Bool initok = Valse;   Const Char * koptoetsen[] = {"User-Agent","Cookie"} ; Kop zum Tracken   size_t headerkeyssize = grootte van(koptoetsen)/grootte van(Char*); Kop zum Tracken   Server.Op("/", handleRoot);   Server.Op("/login", handleLogin);   Server.Op("/newPICC", handleNewPICC);   Server.Op("/erasePICC", handleErasePICC);   Server.onNotFound ( handleNotFound );   Server.collectHeaders(koptoetsen, headerkeyssize );Server anweisen, diese zu Tracken    Server.Beginnen(); Webserver starten   }        ******************** Eindfuncties webserver ************************************************************************************************************************************************************************************


******************* Startfuncties WiFi Management *****************************************************************************************************************************************************************
Funktion von https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/wps-mit-dem-esp8266?ls=de
Bool startWPS() 
{   Bool wpsSucces = Wifi.beginWPSConfig();   Als(wpsSucces) {       Muss nicht immer erfolgreich heißen! Nach einem Timeout ist die SSID leer       Tekenreeks newSSID = Wifi.Ssid();        Als(newSSID.Lengte() > 0) {         Nur wenn eine SSID gefunden wurde waren wir erfolgreich          Opbrengst();          Seriële.println("ATWPS:OK");         referenties opslaan(); Referenties opslaan bij EEPROM              } Anders {         Seriële.println("ATWPS:NOK");       }   }   Terug wpsSucces; 
}

Bool startWiFiClient startWiFiClient() 
{   Bool WiFiClientGestart = Valse;   size_t A0_ADCValue = 0;   Byte I = 0;   Byte connRes connRes = 0;   Seriële.setDebugOutput(Valse);  Zu Debugzwecken aktivieren.    Wifi.Hostname("CrdRdr41667");   Wifi.softAPdisconnect(Waar);   Wifi.Verbreken();   Wifi.Modus(WIFI_STA);   Als(loadCredentials())      {      Wifi.Beginnen(MyWiFiConfig MyWiFiConfig.APSTAName, MyWiFiConfig MyWiFiConfig.WiFiPwd WiFiPwd);      Terwijl (( connRes connRes != 3 ) En( connRes connRes != 4 ) En (I != 30))  als connRes == 0 "IDLE_STATUS - change Statius"       {        I++;       Serial.print("."; Connect vorgang auf der seriellen Schnittstelle beobachten       ESP.wdtFeed();       Vertraging(500);       Opbrengst();       connRes connRes  = Wifi.waitForConnectResult();       }      Als (connRes connRes == 4 ) { als het wachtwoord onjuist is       Seriële.println("ATWIFI:PWDERR");             Wifi.Verbreken();       }      Als (connRes connRes == 6 ) { module is niet geconfigureerd in stationsmodus       Seriële.println("ATWIFI:STAERR");       Wifi.Verbreken();       }      }   Als(Wifi.Status() == WL_CONNECTED)      {     ESP.wdtFeed();      Seriële.Afdrukken("ATIP:");     Seriële.println(Wifi.localIP());     Wifi.setAutoReconnect(Waar); Stel in of de module probeert opnieuw verbinding te maken met een toegangspunt voor het geval de verbinding wordt verbroken.     MDNS-responder instellen     Als (!Mdns.Beginnen("CrdRdr41667"))        {       Seriële.println("ATMDNS:NOK");       } Anders { Mdns.addService("http", "tcp", 80); }        WiFiClientGestart = Waar;     } Anders      {     A0_ADCValue = analoogLezen(A0);     Wir waren nicht erfolgreich, daher starten wir WPS, wenn WPS Taster an A0 während des Resets gedrückt ist     Als (A0_ADCValue > 499)       {         Als(startWPS())            {             ESP.wdtFeed();              Vertraging(500);             Wifi.Verbreken();             Wifi.Modus(WIFI_STA);             Wifi.Beginnen(Wifi.Ssid().c_str(), Wifi.Psk().c_str());             ESP.wdtFeed();              WiFiClientGestart = Waar;           } Anders           {             WiFiClientGestart = Valse;             Wifi.Verbreken();           }       } Anders       {         Wifi.Verbreken();       }    }    WiFi.printDiag(Serieel);       Zu Debugzwecken aktivieren.   Terug WiFiClientGestart; 
}
******************** Eindfuncties WiFi Management ****************************************************************************************************************************************************************

******************* Startfuncties WiFi-referenties opslaan bij EEPROM ********************
Bool loadCredentials() 
{
 Bool RetValue;
 Eeprom.Beginnen(512);
 Eeprom.Toevoegen(0,MyWiFiConfig MyWiFiConfig);
 Eeprom.Einde();
 Als (Tekenreeks(MyWiFiConfig MyWiFiConfig.ConfigValid (ConfigValid)) == "TK")    {     RetValue = Waar;   } Anders   {     RetValue = Valse; WLAN Settings nicht gefunden.   }   ESP.wdtFeed();    Terug RetValue; 
}

Void referenties opslaan() Speichere WLAN geloofsbrieven auf EEPROM 
{   size_t I;   Voor (I = 0 ; I < grootte van(MyWiFiConfig MyWiFiConfig) ; I++) Loeschen der alten Konfiguration      {       Eeprom.Schrijven(I, 0);       }   Voor (I = 0 ; I < STANameLen STANamelen  ; I++) Loeschen der alten Konfiguration      {       MyWiFiConfig MyWiFiConfig.WiFiPwd WiFiPwd[I] = 0;       }   Voor (I = 0 ; I < WiFiPwdLen WiFiPwdLen ; I++) Loeschen der alten Konfiguration      {       MyWiFiConfig MyWiFiConfig.APSTAName[I] = 0;       }      Temp = Wifi.Ssid().c_str();   I = Temp.Lengte();   Temp.toCharArray(MyWiFiConfig MyWiFiConfig.APSTAName,I+1);    Temp = Wifi.Psk().c_str();   I = Temp.Lengte();   Temp.toCharArray(MyWiFiConfig MyWiFiConfig.WiFiPwd WiFiPwd,I+1);   Temp = "";      strncpy strncpy(MyWiFiConfig MyWiFiConfig.ConfigValid (ConfigValid) , "TK", grootte van(MyWiFiConfig MyWiFiConfig.ConfigValid (ConfigValid)) );    Eeprom.Beginnen(512);   Eeprom.zet(0, MyWiFiConfig MyWiFiConfig);   Eeprom.Commit();   Eeprom.Einde();   ESP.wdtFeed(); 
}
******************** EINDfuncties StoreCredentialsto EEPROM ******************************************************************************************************************************************

****************** Start functies Cardservices ****************************************************************************************************************************************************************


Void PCDHardReset()
{   digitalWrite(RST_PIN,Lage);   Vertraging(200);   digitalWrite(RST_PIN,Hoge);   mfrc522.PCD_Reset();   mfrc522.PCD_Init();                              Initialisiere MFRC522 Lesemodul   mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Setzt Antenne auf max. Empfang Empfang Empfang   mfrc522.PCD_AntennaOn();
}

Booleaanse CardAuthenticate(Booleaanse ABKey ABKey, Byte Sector,Byte Ikey[6])
{
Const Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
Byte statusA;
statusA = 0;
Voor (Int A = 0; A < 6;A++)   {   Sleutel.keyByte[A] = Ikey[A];   }   Sleutel A
Als (ABKey ABKey)   {   statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, sectorsleutelbaar[Sector], &Sleutel, &(mfrc522.Uid));   Als (statusA != MFRC522::STATUS_OK)     {     Seriële.println("ATAUTH:ERR_A");     Terug Valse;     }       }   Sleutel B   Anders Als (Niet ABKey ABKey)   {   statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B,sectorsleutelbaar[Sector], &Sleutel, &(mfrc522.Uid));   Als (statusA != MFRC522::STATUS_OK)     {     Seriële.println("ATAUTH:ERR_B");     Terug Valse;     }        }
Terug Waar;   }

WriteData . gebruikt Global Variable DataBuffer voor datareturn
Booleaanse CardDataWrite CardDataWrite(Byte Sector,Byte Blok,Byte Waarde[16])
{
Byte Status;
Byte schrijfvector;
Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
schrijfvector = Sector * 4 + Blok -1 ;
Voor (Byte A = 0; A < 16; A++)   {   Als (schrijfvector ==  sectorsleutelbaar[A])     {     Serial.println("NAK";     Terug Valse;     }   }
Status = mfrc522.MIFARE_Write(schrijfvector, Waarde, 16);
Als (Status != MFRC522::STATUS_OK)   {   Seriële.println("ATPCD:W_ERR");   Serial.println(mfrc522. GetStatusCodeName(status));   Terug Valse;   } Anders    {   Serial.print("OK");   Terug Waar;   }   }

Leesgegevens - gebruikt Globale variabele databuffer voor gegevensretour
Booleaanse CardDataRead(Byte Sector,Byte Blok)
{
Byte statusi;
Byte leesvector;
Const Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
Byte Formaat = 18;
leesvector = Sector * 4 + Blok -1 ;
Voor (Byte A = 0; A < 16; A++)   {   Als (leesvector ==  sectorsleutelbaar[A])     {      Seriële.println("ATPCD:R_ERR");       Terug Valse;     }   }
statusi = mfrc522.MIFARE_Read(leesvector, Gegevensbuffer, &Formaat);
Als (statusi != MFRC522::STATUS_OK)   {   Seriële.println("ATPCD:R_ERR");   Terug Valse;   } Anders    {   Terug Waar;   }   }

Booleaanse ResetCardtoDefault()
{
Byte Ikey[16];
Byte Status,I;
Byte schrijfvector;
Const Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
schrijfvector = sectorsleutelbaar[USED_Sector];
Als (CardAuthenticate(KEYB,USED_Sector,MifareClassicKey.Key_B)) Sector Autenticate voor WRITE Access      {       Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; }           Als (!(CardDataWrite CardDataWrite(USED_Sector,1,Gegevensbuffer))) { Terug Valse; }        Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; }          Als (!(CardDataWrite CardDataWrite(USED_Sector,2,Gegevensbuffer))) { Terug Valse; }       Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; }          Als (!(CardDataWrite CardDataWrite(USED_Sector,3,Gegevensbuffer))) { Terug Valse;}      }
Voor (Byte I = 0; I <= 16; I++) { Ikey[I] = 255; }  Standaardsleutel laden voor alle sectoren 
Ikey[6] = 0xFF; Standaardinstelling voor Access Bits
Ikey[7] = 0x07; // 
Ikey[8] = 0x80; // 
Ikey[9] = 0x69;    Status = mfrc522.MIFARE_Write(schrijfvector, Ikey, 16);
Als (Status != MFRC522::STATUS_OK)   {   Terug Valse;   }
Terug Waar;   }

Booleaanse SetSectorAccessControl (Byte Sector,Byte Akey[6],Byte Bkey Bkey[6])
{
Byte Ikey[16];
Byte Status;
Byte schrijfvector;
Const Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
schrijfvector = sectorsleutelbaar[Sector];
Ikey[0] = Akey[0];
Ikey[1] = Akey[1];
Ikey[2] = Akey[2];
Ikey[3] = Akey[3];
Ikey[4] = Akey[4];
Ikey[5] = Akey[5];
Ikey[6] = 0x78; Data block 0-3 Toegangsvoorwaarden: Key B schrijven / Key A Lezen
Ikey[7] = 0x77; KEY A & KEY B & Acces Bits Schrijven:Key B / Key A Leestoegang Bits
Ikey[8] = 0x88; Calculator: http://calc.gmss.ru/Mifare1k/
Ikey[9] = 0x69; Fixer Wert - > standaard hex 69
Ikey[10] = Bkey Bkey[0];
Ikey[11] = Bkey Bkey[1];
Ikey[12] = Bkey Bkey[2];
Ikey[13] = Bkey Bkey[3];
Ikey[14] = Bkey Bkey[4];
Ikey[15] = Bkey Bkey[5];
Status = mfrc522.MIFARE_Write(schrijfvector, Ikey, 16);
Als (Status != MFRC522::STATUS_OK)   {   Seriële.println("ATPCD:W_KEY_ERR");   Terug Valse;   }Anders    {   Terug Waar;   }   }

Booleaanse CheckforDefaultCardKey ()
{
Byte tkey[6];
Booleaanse Kaartresultaat; 
Byte leesvector;
Byte statusi;
Const Byte sectorsleutelbaar [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
Byte Formaat = 18;
Voor (Byte I = 0; I <= 6; I++) { tkey[I] = 255; }  Standaardsleutel laden voor alle sectoren 
Kaartresultaat = Waar;   Als (!CardAuthenticate(Keya,USED_Sector,tkey)) { Kaartresultaat = Valse; };
leesvector = sectorsleutelbaar[USED_Sector];
statusi = mfrc522.MIFARE_Read(leesvector, Gegevensbuffer, &Formaat);
Als (statusi != MFRC522::STATUS_OK) { Kaartresultaat = Valse; } 
als (!) (DataBuffer[7] = 0x07) & (DataBuffer[7] = 0x80)) { CardResult = false; };
Terug Kaartresultaat; 
}

Booleaanse WriteNewMiFareClassicPICC ()   {   Byte tkey[6];   Byte I,A;   Booleaanse Kaartresultaat;   Als (CheckforDefaultCardKey())     {     Voor (I = 0; I <= 6; I++) { tkey[I] = 255; }  Standaardsleutel laden voor alle sectoren      Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; } Variabele buffer wissen     Kaartresultaat = Waar;            Als (CardAuthenticate(Keya,USED_Sector,tkey)) Sector Autenticate       {       Serial.println("Auth Sec 0 OK");        Als (Achternaam.Lengte() > 15) { A = 15; } Anders { A = Achternaam.Lengte();}       Als (Achternaam.Lengte() > 0)         {         Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; }             Voor (I = 0; I <= A; I++) { Gegevensbuffer[I] = Achternaam[I]; }            Als (!(CardDataWrite CardDataWrite(USED_Sector,2,Gegevensbuffer))) { Kaartresultaat = Valse; } Sector 0 Blok 2 Vorname mit Key A schreiben         }       Als (Givenname.Lengte() > 15) { A = 15; } Anders { A = Givenname.Lengte(); }       Als (Givenname.Lengte() > 0)         {         Voor (I = 0; I <= 16; I++) { Gegevensbuffer[I] = 0; }          Voor (I = 0; I <= A; I++) { Gegevensbuffer[I] = Givenname[I]; }          Als (!(CardDataWrite CardDataWrite(USED_Sector,3,Gegevensbuffer))) { Kaartresultaat = Valse; } Sector 0 Blok 3 Nachname mit Key A schreiben         }             Als (!(SetSectorAccessControl (USED_Sector,MifareClassicKey.Key_A,MifareClassicKey.Key_B))) { Kaartresultaat = Valse; }    (bytesector,byte Akey[6],byte Bkey[6])       } Anders {               Kaartresultaat = Valse;              Terug Kaartresultaat;              }        } Anders {               Kaartresultaat = Valse;              Terug Kaartresultaat;              }          Als (Kaartresultaat)        {        Serial.println("PICC geschreven";            Kaartresultaat = Waar;       }     Anders        {        Serial.println("PICC niet leeg");       Kaartresultaat = Valse;       }     Opbrengst();       Terug Kaartresultaat;   }


Booleaanse ReadMiFareClassicPICC ()
{
Booleaanse Kaartresultaat;
Byte I,A ;
Kaartresultaat = Waar;    Als (CardAuthenticate(Keya,USED_Sector,MifareClassicKey.Key_A)) Sector Autenticate met LEES Sleutel A   {   Givenname = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; Tijdelijke aanduiding   Achternaam = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; Tijdelijke aanduiding   Voor (I = 0; I < 18; I++) { Gegevensbuffer[I] = 0; } Variabele buffer wissen   Als (CardDataRead(USED_Sector,2)) Feld Vorname auslesen     {         Voor (I = 0; I < 16; I++) { Achternaam[I] = Char(Gegevensbuffer[I]);  }             } Anders {             Terug Valse;            }     Voor (I = 0; I < 18; I++) { Gegevensbuffer[I] = 0; } Variabele buffer wissen          Als (CardDataRead(USED_Sector,3)) Feld Nachname auslesen       {                Voor (I = 0; I < 16; I++) { Givenname[I] = Char(Gegevensbuffer[I]); }              } Anders {               Terug Valse;                 }      } Anders      {      Terug Valse;     }
Seriële.Afdrukken ("ATAUTH_S:");
Seriële.println (Achternaam);
Seriële.Afdrukken ("ATAUTH_G:");
Seriële.println (Givenname);
Terug Waar;
}

Void CardServer()
{
#define PCD_Poll_Interval 400
#define PCD_Watchdog_Interval 60000
Als (millis() - PCD_ServiceCall_Handler >= PCD_Poll_Interval)    {    PCD_ServiceCall_Handler = millis();        Als (mfrc522.PICC_IsNewCardPresent())   PICC = nabijheid geïntegreerde circuitkaart = kontaktlose Chipkarte     {      mfrc522.PICC_ReadCardSerial();       Opbrengst();     Unterscheidung nach Kartentyp     0x08 für MIFARE Classic 1K     0x18 für MIFARE Classic 4K     0x11 für MIFARE PLUS     Als (mfrc522.Uid.Sak == 0x08 || mfrc522.Uid.Sak == 0x18)       {       MiFare_Classic_Processor START (mfrc522.uid.sak);  Nur ausführen wenn Eine Mifare Classic Karte vor den Leser gehalten wurde.       Byte tkey[6];        Voor (Byte I = 0; I <= 6; I++) { tkey[I] = 255; }  Standaardsleutel laden voor alle sectoren        Als(LearnNewCard) neue Karte soll angelernt werden.         {           Als (WriteNewMiFareClassicPICC()) { SetRGBLed(0,255,0,Valse); } Anders { SetRGBLed(255,0,0,Valse); }         }       Anders Als (EraseCard)  KartenDaten sollen gelöscht werden.         {           Als (ResetCardtoDefault()) { SetRGBLed(0,255,0,Valse); } Anders { SetRGBLed(255,0,0,Valse); }         }             Anders         {         Als (ReadMiFareClassicPICC())            { Karte gültig !           Bool PinState= digitaalLezen(RELAIS_PIN);           PinState = !PinState;           digitalWrite(RELAIS_PIN, PinState);           SetRGBLed(0,255,0,Valse);        Led Grün           } Anders { SetRGBLed(255,0,0,Valse); }               }       LearnNewCard = Valse;                     MiFare_Classic_Processor STOP (mfrc522.uid.sak);       } Anders Als (mfrc522.Uid.Sak == 0x00) Mifare Ultralight       {         SetRGBLed(255,0,0,Valse);       } Anders       {         SetRGBLed(255,0,0,Valse);         Serial.print("PICC Type niet ondersteund. Type:");          Serial.println(mfrc522.uid.sak); Erweiterung: evtl andere Kartentypen         }     mfrc522.PCD_StopCrypto1();     mfrc522.PICC_HaltA();     Vertraging(2000);     SetRGBLed(0,0,255,Valse);        Led Farbe Blau Leser ist in Grundzustand     }   }   Als (millis() - PCD_WatchDog_Handler >= PCD_Watchdog_Interval)    {    PCD_WatchDog_Handler = millis();    Resultaat = mfrc522.PCD_PerformSelfTest();    Opbrengst();    mfrc522.PCD_Init();                       Initialiseer MFRC522 Leesmodule opnieuw    mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); Stelt antenne op max. ontvangst    mfrc522.PCD_AntennaOn();     Opbrengst();    Als (!(Resultaat))      {       PCDHardReset();       Seriële.println("ATPCD:ERR_H");     }    }   }

Stop functies CardServices ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************


 
Void Lus()  Hoofdlus
{   CardServer();          Kaartlezer om specifieke aanvragen af te handelen   Opbrengst();    Server.handleClient(); Aanvragen voor webserver bewerken    ESP.wdtFeed();       Watchdog. Uitschakelen met "wdt_disable();"
}

 

De Wlan-verbindingsgegevens blijven behouden omdat we deze in een niet-vluchtig geheugen in de vorige schets hebben opgeslagen.

Maar hoe werkt de authenticatie van de kaart nu?

Simpel gezegd, bij het houden van een MiFare Classic kaart (dit is van tevoren gecontroleerd), de kaartlezer module probeert te lezen een sector die alleen kan worden gelezen met een geldige sleutel.

Als de actie is geslaagd, worden de voornaam en achternaam van de naamvelden voorgelezen en wordt de kaart als geldig herkend. (relais is ingeschakeld) Als verificatie mislukt of de verkeerde sleutel wordt gebruikt, wordt de kaart afgewezen als ongeldig.

Het onderscheid tussen "kaart geldig of kaart ongeldig" op deze eigenschap geeft ons de volgende voordelen:

Meerdere kaarten kunnen recht hebben op een lezer op hetzelfde moment, zonder welke elke kaart moet worden bekend gemaakt aan de lezer op voorhand door UUID.

Verschillende kaartlezers kunnen worden bediend met een kaart op hetzelfde moment zonder dat elke kaartlezer al weten elke kaart op voorhand via UUID.

Door de sectordefinitie of het sleutelmateriaal te variëren, kunnen "toestemmingscirkels" worden gevormd.

 

We zijn nu het creëren van onze eerste autorisatiekaart. Om dit te doen, na het inloggen op het menu-item "PICC", dan "Maak een nieuwe kaart" en klik erop. We zien de volgende pagina:

We voeren een voor- en achternaam in de aangewezen velden in en drukken op de knop 'Maak een smartcard maken'

De LED kleurt geel. We hebben nu een LEERE!! Mifare Classic kaart voor de lezer en wacht kort tot de LED groen wordt. Dat is het! Vanaf nu kunnen we deze kaart gebruiken als geautoriseerde kaart voor onze lezer.

Als we deze kaart willen ongeldig maken, gaan we na het inloggen op het menu-item PICC onder 'Kaart verwijderen' en klikken erop. -- Na het bericht:

we houden de eerder geautoriseerde kaart terug voor de lezer. Dit is dan ongeldig.

Veel plezier met het recreëren van ons tot het volgende deel.

Esp-8266Für arduinoProjekte für fortgeschritteneSmart home

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert

Aanbevolen blog berichten

  1. Installeer ESP32 nu van de raad van bestuur
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP Programmeren via Wi-Fi