Accesso limitato ai dispositivi tramite scheda contactless con NodeMCU e modulo RC522 parte 4 - Down the Rabbit Hole

Il blog di oggi, come promesso, "in fondo al Rabbit Hole" e ci occupiamo degli stagisti di MiFare Proximity Integrated Carte senza contatto Serie. Serie.Esaminiamo le peculiarità e guardiamo più attentamente le funzioni.

Molti Lettore di schede-Progetti basati sul chip M522 Arduino. che ho visto personalmente, purtroppo, non utilizzano nella tecnologia di sicurezza o nelle possibilità ciò che la carta Mifare Classic ci offre in funzioni.

Questi progetti sono limitati alla lettura dell'ID univoco (UUID) della scheda liberamente leggibile per ogni lettore di carte e telefono cellulare e alla verifica con un elenco di UUID consentiti.Se questo è incluso nell'elenco, la carta è considerata valida.

Anche nel nostro parti precedenti Noi utilizziamo questo principio.Vogliamo cambiare questo con la nostra applicazione blog oggi e garantire i dati sulla nostra carta MiFare Classic.

Il tipo di carta MiFare Classic utilizzato in questo progetto (si prega di notare anche questa nota) ci permette di memorizzare le nostre informazioni dalla mappa e proteggerlo da lettura o modifica non autorizzata.

A tal fine, i settori (0-15) con ogni 4 *16 byte sono già disponibili dal produttore, ad eccezione del settore 0,3*16 byte che possono essere liberamente descritti.16 byte di ogni settore sono chiamate il settore Trailer e utilizzati per memorizzare le due chiavi del settore e per definire la matrice di accesso.

I 16-byte di un settore dei rimorchi sono suddivisi come segue:
6 Bytes Primo settore chiave
6 Bytes seconda chiave del settore
Definizione del permesso di accesso 4 Bytes

Ora vogliamo memorizzare sulla nostra mappa i nomi e cognome criptati da noi.Per questo definiamo un settore (1-15) sopra la costante...che abbiamo intenzione di utilizzare a questo scopo.Ho scelto il blocco del settore uno nel codice.

Il primo nome dovrebbe essere nel secondo campo 16-byte, e il cognome nel terzo campo 16-byte.Il primo campo 16-byte è riservato alle estensioni future.

Inoltre, abbiamo bisogno di una definizione chiave che conserviamo nella struttura MiFareClassicKeyTable.

Si prega di cambiare questo blocco (2x 6 byte) con il proprio materiale chiave durante la costruzione e salvarlo in un luogo sicuro, altrimenti chiunque conosca questo progetto con il materiale chiave menzionato nel codice in testo chiaro leggerà la tua carta e la propria valid a!può creare mappe per il controllo del dispositivo.

Piccolo Spoiler: Inoltre, avremo nuovamente bisogno di questo materiale chiave in caso di una successiva continuazione della serie.Tenete presente che descrivete la mappa e cambiate le opzioni di sicurezza. Questo rende possibile la mappa.non è più utilizzabile per altri scopi!

Dopo aver cambiato il materiale chiave, carichiamo il seguente codice sul nostro ESP:

 

«35; comprende <SPI.h>
«35; comprende <MFRC522.h>
«35; comprende <ESP8266WiFi.h>
/'35; includono <WiFiClient.h> 
«35; comprende <ESP8266WebServer.h>
«35; comprende <ESP8266mDNS.h>
«35; comprende <PROM.h>
«35; comprende <FS.h>           // Include la libreria SPIFFS

35; definire PIN RST     5     // SPI Reset Pin (output D1)
35; definire PIN DI RELISI  16    // Relais (output D0) [BASSA Active]- Anche LED interno vicino alla porta USB
35; definire PIN SS-U      15    // slavo SPI Seleziona Pin

35; definire RGBLED R    2     // Rosso (uscita D4) 
35; definire RGBLED G    0     // Verde (output D3) Anche i LED interni sul modulo ESP
35; definire RGBLED B    4     // Blu (uscita D2)

35; definire WiFicwdLen   25   // Massima lunghezza della password WiFi
35; definire STATO 20     // Massima SSIDlunghezza WiFi
35; definire ESPHost 20 // Numero massimo di caratteri ESPHost

35; definire CHIAVE Vero         //codice di bandiera PIC
35; definire CHIAVE false        //codice di bandiera PIC

35; definire BUILTIN LED 16
35; definire PIN WIRE SDA 4 
35; definire PIN WIRE SCL 5 

35; definire Settore UTILIZZATO 1  // Settore Carta utilizzato per i dati di autenticazione e di configurazione (valido: 1-15)

MODO ADC(ADC TOUT);   // Configura l'input analogico di A0 all' esterno.ADC-u TOUT (per la tensione esterna), ADC-u VCC (per la tensione di sistema). 
MFRC522 mrc522(PIN SS-U, PIN RST);   // Crea istanza MFRC522
MFRC522::Chiave MIFARE chiave;
ESP8266WebServer server(80);        // Creare il sito web del server

Stretto WiFi   {     Heavyiron ESPHost[ESPHost];      Heavyiron APSTA[STATO]; // STAZIONE Nome da collegare, se contaminato     Heavyiron WiFiPwd[WiFicwdLen]; // WiFiPAssword, se contaminato     Heavyiron Configura[3]; //Se Config è Vaild, è richiesto il tag "TK"   };    Stretto MiFareClassic   {    scambio Chiave A[6] = {0x22,0x44,0xFA,0xAB,0x90,0x11};   // Cambia chiave per la scheda PIC.     scambio Chiave B[6] = {0xFE,0xE1,0xAA,0x3,0xDF,0x37};   // Cambia chiave per la scheda PIC.     Heavyiron Configura[3]; //Se Config è Vaild, è richiesto il tag "TK"   };    MiFareClassic MiFareClassic;
WiFi MyWiFiConfig;

// Variabili globali
bl Risultato  = false;
bl Learn NewCard = false;
bl EraseCard. = false; 
bl ExpirationDateActive = false;
Stringa Raw;
Stringa Nome;
Stringa Scadenza;
Stringa Tempi;
inadatto lunga SessionID;
inadatto lunga PCD Service Call Trader = 0;
inadatto lunga Gestore di watchdog PCD = 0;
u t DataBuffer[18]  = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };


vuoto setComment()     {    pinMode(PIN RST,PRODUZIONE);   digitalacWrite(PIN RST,ALTA);   pinMode(PIN DI RELISI,PRODUZIONE);   pinMode(RGBLED R,PRODUZIONE);   pinMode(RGBLED G,PRODUZIONE);   pinMode(RGBLED B,PRODUZIONE);   digitalacWrite(PIN DI RELISI,ALTA);    Relais inattivo   Impostazioni(255,0,255,false);       Inizializzazione dei colori//Led Color Lila   Serial.Inizio(115200);               Iniziare la comunicazione seriale con PC con costruzione 115200   Serial.Stampa("");   Tempi = Ricevuto.+ Stringa(ESP.getChipName());   Serial.Stampa(Tempi);   // Serial.print("ADC Value:");Serial.println(analogicRead(A0));   SPI.Inizio();                      // Inizializzazione della comunicazione SPI   PCDHardReset();   SessionID = millimetri();    Risultato  = startWiFiClient();     Inizializzazione HTTPPSServer();   Impostazioni(0,0,255,false);       //Leather Color Blue Inizializzazione completa   //ESP.wdtAbility(WDT 4S);// Start Watchdog   }


***********************************************

vuoto Impostazioni(scambio RedValue,scambio GreenValue,scambio BlueValue,booleano Slovacchia)  //Radio kion per il controllo di RGB Led
{   digitalacWrite(RGBLED R,BASSA);       digitalacWrite(RGBLED G,BASSA);   digitalacWrite(RGBLED B,BASSA);    se (RedValue == 255)   { digitalacWrite(RGBLED R,ALTA); }      se (GreenValue == 255) { digitalacWrite(RGBLED G,ALTA); }   se (BlueValue == 255)  { digitalacWrite(RGBLED B,ALTA); }    }

*********************************************

Avvia funzionalità Webserver

//Basic cookie routine si basano sull’estratto di GIT:
//https://github.com/esp8266/ESPWebServer/blob/master/examples/SimpleAuthentification/SimpleAuthentification.ino
bl au au au au()
{     se (server.hasHeader(Biscotto.)){       // Cookie trovato      Tempi = server.intestazione(Biscotto.);       //Serial.println(temp);      Stringa Sessione = Stringa(ESP.getChipName()) + "=" + Stringa(SessionID);      rendimento();      se (Tempi.indice(Sessione) != -1) {         // Web Autenticazione riuscita        Tempi = "";        ritorno Vero;       }     }        // Web Autenticazione non riuscita    Tempi = "";    SessionID = millimetri();    ritorno false; 
} 

vuoto handleLogin(){   Stringa CleverMouse;   //String cookie = server.header("cookie");   //Serial.println(cookie);   se (server.hasohGenericName("DISCONNECT")){     //Utenti di disconnessione;     server.Select(Posizione,"/login");     server.Select(Cache-Control,"no-cache");     SessionID = millimetri();     Tempi = Stringa(ESP.getChipName()) + "= NA; HttpOnly; SameSite=Stretto";     server.Select(Autunno,Tempi);     Tempi = "";     server.inviare(301);     rendimento();     ritorno;   }   se (server.hasohGenericName("USERNOME") && server.hasohGenericName(PASSWORD)){     Tempi = Stringa(ESP.getChipName());     se (server.arrabbiato("USERNOME") == admin &&  server.arrabbiato(PASSWORD) == Tempi ){       server.Select(Posizione,"/");       server.Select(Cache-Control,"no-cache");       SessionID = millimetri();       Tempi = Stringa(ESP.getChipName()) + "=" + Stringa(SessionID) + "; HttpOnly; SameSite=Right";       server.Select(Autunno,Tempi);       Tempi = "";       server.inviare(301);       rendimento();       ritorno;     }   CleverMouse = "<script>alert (nome utente sbagliato o password));</script>";   }    CSS intestazione modello();    rendimento();    Tempi = "<Head><title>Login</title></Head><<<<DIV ALIGN=CENTER>";    server.sendContent(Tempi);    Tempi = "<h2>Registration to RC522</h2><body><br><table border=0 bgcolor=black><tr><DIV ALIGN=GIUSTO>";    server.sendContent(Tempi);    Tempi = "<form action='/login'mean='post'>Username: <input type=text Name='USERNAME'Size=17 required><br>";    server.sendContent(Tempi);    Tempi = "Password: <input type=password name='PASSWORD'Size=17 required><br><<<button type='subject'"";    server.sendContent(Tempi);    Tempi = "name='Login'u Button'value='1'style='heard: 30px; width: 100px'> Login</button><, br></th>/tr></form>;</DIV gt&t;;;;";    server.sendContent(Tempi);    Tempi = "<br><SMALL> </SMALL> <;;</SMALL>";      server.sendContent(Tempi);    Tempi = CleverMouse + "</DIV></body></HTML>";    server.sendContent(Tempi);    Tempi = "";
}

vuoto handleNotefound()    {   SessionID = millimetri();   Tempi = Pagina non trovata.;   Tempi += URI:;   Tempi += server.e();   Tempi += "nMethod:;   Tempi += (server.metodo() == HTTP GET)?"GET":POST;   Tempi += "nArgoments:;   Tempi += server.Arrabbiato();   Tempi += "n";   per (u t i=0; i<server.Arrabbiato(); i++){     Tempi += " " + server.Arrabbiato(i) + ": " + server.arrabbiato(i) + "n";   }   rendimento();   server.inviare(404, "testo/pianura", Tempi);   Tempi = "";   }



vuoto handleErasePIC()
{   se (!au au au au())     {     server.Select(Posizione,"/login");     server.Select(Cache-Control,"no-cache");     server.inviare(301);     rendimento();     ritorno;     }     CSS intestazione modello();   rendimento();   Tempi = "<Head><title>card reader RC522</title></head><body>";   server.sendContent(Tempi);   HtmlNavStructure();   Tempi = "<script>alert('Tenete la carta da cancellare dal lettore));</script>";      server.sendContent(Tempi);    rendimento();   Impostazioni(0,255,255,false);       //Led Color cian programming mode   EraseCard. = Vero;         Tempi = "</body></html>";   server.sendContent(Tempi);   server.cliente().Stop!();   Tempi = "";
}


vuoto handleNewPIC()
{   se (!au au au au())     {     server.Select(Posizione,"/login");     server.Select(Cache-Control,"no-cache");     server.inviare(301);     ritorno;     }   se (server.hasohGenericName(Cognome) && server.hasohGenericName("Nome"))   {      Raw = server.arrabbiato(Cognome);     Nome = server.arrabbiato("Nome");     Scadenza = server.arrabbiato(Scadenza);     se (server.hasohGenericName("ExpDateOption")) { ExpirationDateActive = Vero; } e { ExpirationDateActive = false; }     Tempi = "<script>alert('Per favore tenete la nuova carta davanti al lettore!);</script>";        server.sendContent(Tempi);      Impostazioni(255,255,0,false);       //Led Color Yellow Programming Mode     Learn NewCard = Vero;     rendimento();     ritorno;       }         CSS intestazione modello();   rendimento();   Tempi = "<Head><title>card reader RC522</title></head><body>";   server.sendContent(Tempi);   HtmlNavStructure();   Tempi = "";   Tempi = "<table border=0 ALIGN=CENTER><th>";   server.sendContent(Tempi);   Tempi = "<table border=1 bgcolor = black><<form action='/newPICC'mety='post'>";   server.sendContent(Tempi);   Tempi = "<tr><th>Cartholder:<br><div ALIGN=GIUSTO>";   server.sendContent(Tempi);   Tempi = "Nome: <input type=text name='Surname'Size=17 maxlenght=16 placeholder='Max'required><br>";   server.sendContent(Tempi);   Tempi = "Cognome: <input type=text Name='Givenname'Size=17 maxlenght=16 placeholder='Mustermann'required><br>";   server.sendContent(Tempi);   Tempi = "</div></th><th>Map metadati:<br><DIV ALIGN=GIUSTO>";   server.sendContent(Tempi);       Tempi = "<input name='ExpDateOption'TIPO=checkbox VALUE=1 >data di scadenza:<input type=data Name='ExpDate'Size = 17 >";   server.sendContent(Tempi);   Tempi = "<br><th><tr><th><<<<br>";   server.sendContent(Tempi);   Tempi = "<button type='subject'name='NewCard'value='1'style='heard: 30px; width: 200px >Create New Smartcard</button>";   server.sendContent(Tempi);   Tempi = "<br></form></tr></th></table>";   server.sendContent(Tempi);   Tempi = "</body></html>";   server.sendContent(Tempi);   server.cliente().Stop!();   rendimento();     Tempi = "";
}

vuoto handleRoot()
{   se (!au au au au()){     server.Select(Posizione,"/login");     server.Select(Cache-Control,"no-cache");     server.inviare(301);     ritorno;     }   // contenuto HTML   CSS intestazione modello();   rendimento();   Tempi = "<Head><title>card reader RC522</title></head><body>";   server.sendContent(Tempi);   HtmlNavStructure();   Tempi = "<div ALIGN=CENTER><br><br><br><BIG>Benvenuti al sito web di lettori di carte intelligenti RC522.</BIG>";   server.sendContent(Tempi);   Tempi = "Viaggio: + Stringa(ESP.getReimportazione()) + "<br>";   server.sendContent(Tempi);   Tempi = "Free Heat Storage: + Stringa(ESP.getFreeHeap()) + "Bytes<br>";   server.sendContent(Tempi);   Tempi = "Int. Flash: + Stringa(ESP.getFlashChipRealSize()) + "Bytes<br>";   server.sendContent(Tempi);   Risultato = mrc522.PCD PerforamSelfTest();    mrc522.PCD Init();                       // Inizializzazione del modulo di lettura MFRC522   mrc522.PCD SetannaGain(mrc522.RxGain max); // Imposta l'antenna alla massima ricezione   mrc522.PCD-u Antenna();    rendimento();   se (Risultato) {Tempi = "Stato PCD RC522: OK<br>"; } e {Tempi = "Stato PCD RC522: Errore!<br>"; }    server.sendContent(Tempi);   Tempi = "Codice CPU: + Stringa(ESP.getChipName()) + " @ " + Stringa(ESP.getCpuqMHz()) + "MHz<br>";    server.sendContent(Tempi);   Tempi = "<br>Sei stato registrato con successo!<br><form action='/login'mean='get'>";   server.sendContent(Tempi);   Tempi = "<button type='subject'name='DISCONNECT'value='YE'style='heaght: 30px; width: 200px' >Logout</button>";   server.sendContent(Tempi);   Tempi = "</form></div></body></html>";   server.sendContent(Tempi);   se (server.hasohGenericName(Autunno) )  // Sistema di reboot      {     //ESP.wdtFeed();     ESP.wdtDisable();     Tempi = "<script>alert('The system riavvies NOW);</script>";        server.sendContent(Tempi);     server.cliente().Stop!();     rendimento();     Tempi = "";     ESP.reset();     ritardo(4000);      }     server.cliente().Stop!();   Tempi = "";
}

vuoto CSS intestazione modello() // Formato modello per tutti i siti web di ESP interni. https://wiki.selfhtml.org/wiki/CSS   {    server.setContentLength(CONTENUTO sconosciuto);    Tempi = "";    server.inviare (200, "text/html", Tempi);    Tempi = "<?DOCTYPE HTML PUBBLICO'-//W3C//DTD HTML 4.01 Transitional//EN'><html lang='de'><meta charset='UTF-8'>";    server.sendContent(Tempi);    Tempi = Tylsty=/ testo/css&&&igg;*{margine: 0;padding: 0;;;}corpo di persone{sottofondo:nero;colore:darkoirchid; dimensione del font: 16px;" server.>>>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;">"font-family: sans-serif,arial;}.nav{width: 1300px;altezza: 30px;margine: 0 auto;border-radio: 5px;";    server.sendContent(Tempi);    Tempi = Se vuoi fare questo, sarai in grado di usare l'altezza della linea: 60px; posizione: relativa; posizione: posizione: relativa; sfondo: sfondo: Darkochichid; sfondo: sfondo: sfondo: backbackbackin: in questo modo, potrai essere in grado di utilizzare la linea-altezza: 60px; posizione; posizione: relativa; sfondo: sfondo: backbackback: darkorchchid; back: back: backbackbackbackbackbackback,;;>>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;">= "box-shadow: 0px 2px 5px 0px grigio;text-allineation: center;float: left;ground-color:'35; 010000;">"box-shadow;    server.sendContent(Tempi);    Tempi = "posizione: assoluta;}.nav > ul > li:nth-of-type(1){raggio di frontiera: 5px 0px 0px 5px;}.nav > ul > li:nth-of-type(5)";    server.sendContent(Tempi);    Tempi = "{border-radio: 0px 5px 5px x x x;;;}lli ni ni un colore: a rgb(181818181818181818181818181818181818; larghlarghlarghlarghlarghlarghlarghlarghlargha20px; altezza: 55px; impaimpaimpaimpainin- in- il-bloc;"""<<>>>>>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;">"testo-decorazione: nessuno;} li a:hover{font-weight: audace;border-bottom: 2px solido \35; f;}ul li ul ul ul ul display: nessuno;}";    server.sendContent(Tempi);    Tempi = Se vuoi vedere lo show: blocco;}.fa{margine-destro: 5px;.container{widspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspanspans434f54;"sendContenttemp temp temptemp temp= "margine: 0 auto;padding:20px 20px;}@media screen e (max-width: 480px){header{width: 100%;}";    server.sendContent(Tempi);    Tempi = «.nav {esposizione: nessuno; larghezza: il 100%; altezza: automobile;} ul li {larghezza: il 100%; galleggiante: nessuno;} ul li {larghezza: il 100%»;  ;   il server   disegna =.   sendContent   (  l'impiegato temporaneo  )   disegna =;   l'impiegato temporaneo   =  ;    server.sendContent(impiegato temporaneo);    impiegato temporaneo = «.container {larghezza: il 100%; altezza: auto;} corpo {eccedenza-x:hidden; }} </style>»;;    server.sendContent(impiegato temporaneo);    impiegato temporaneo = "";   }


vuoto HtmlNavStructure()   {   impiegato temporaneo = «<div classe = 'menu'><nav classe = 'nav'><ul>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «<li><a href = '# '>System</a>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «<ul><li><a href = '/'>Information</a></li>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «<li><a href = '/? Reboot=YES'>Neustart</a></li>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «</ul>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «</li><li><a href = '# '>PICC</a>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «<ul><li><a href = mappa di '/newPICC'>Neue erstellen</a></li>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «<li><a href = '/erasePICC'>Karte löschen</a></li></ul>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «</li>»;;   //lavori come impiegato temporaneo = «</li><li><a href = '# '>Ereignisprotokoll</a></li>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = «</ul></nav></div>»;;   server.sendContent(impiegato temporaneo);   impiegato temporaneo = "";   }       vuoto InitalizeHTTPServer()    {   bool initok = falso;   può lavoro a giornata * headerkeys[] = {«L'agente di utente»,«Biscotto»} ; //Testata a Tracken   size_t headerkeyssize = sizeof(headerkeys)/sizeof(lavoro a giornata*); //Testata a Tracken   server.su("/", handleRoot);   server.su(«/richiesta di connessione», handleLogin);   server.su(«/newPICC», handleNewPICC);   server.su(«/erasePICC», handleErasePICC);   server.onNotFound ( handleNotFound );   server.collectHeaders(headerkeys, headerkeyssize );//I server istruiscono, questo a Tracken    server.cominciare(); //Inizio di server Web   }        //server Web di Funzioni di ******************* *********************************************


//i ******************* iniziano Funzioni la direzione di WiFi *************************************
//Funzione da https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/wps-mit-dem-esp8266?ls=de
bool startWPS() 
{   bool wpsSuccess = WiFi.beginWPSConfig();   se(wpsSuccess) {       // Muss nicht immer erfolgreich heißen! Nach einem Timeout ist die SSID leer       Stringa newSSID = WiFi.SSID();        se(newSSID.lunghezza() > 0) {         // Nur wenn eine SSID gefunden wurde wir waren erfolgreich          resa();          di Serie.println("ATWPS:OK");         saveCredentials(); // Salva le Credenziali per EEPROM       } altro {         Seriale.println("ATWPS:NOK");       }   }   ritorno wpsSuccess; 
}

bool startWiFiClient() 
{   bool WiFiClientStarted = false;   size_t A0_ADCValue = 0;   byte i = 0;   byte connRes = 0;   di Serie.setDebugOutput(false);  // Zu Debugzwecken fare clic.    WiFi.hostname("CrdRdr41667");   WiFi.softAPdisconnect(vero);   WiFi.scollegare();   il WiFi.in modalità(WIFI_STA);   se(loadCredentials())      {      WiFi.iniziare(MyWiFiConfig.APSTAName, MyWiFiConfig.WiFiPwd);      mentre (( connRes != 3 ) e( connRes != 4 ) e (i != 30))  //se connRes == 0 "IDLE_STATUS - cambiare Stazio"       {        io++;       // Serial.print("."); // Connessione vorgang auf der seriellen Schnittstelle beobachten       //ESP.wdtFeed();       delay(500);       resa();       connRes  = WiFi.waitForConnectResult();       }      se (connRes == 4 ) { // se la password non è corretta       Seriale.println("ATWIFI:PWDERR");             WiFi.scollegare();       }      se (connRes == 6 ) { // modulo non è configurato in modalità       Seriale.println("ATWIFI:STAERR");       WiFi.scollegare();       }      }   se(WiFi.di stato() == WL_CONNECTED)      {     //ESP.wdtFeed();      Serial.print("ATIP:");     Serial.println(WiFi.localIP());     WiFi.setAutoReconnect(true); // Imposta se il modulo tenterà di riconnettersi a un punto di accesso in caso di disconnessione.     // Installazione MDNS risponditore     se (!MDNS.iniziare("CrdRdr41667"))        {       di Serie.println("ATMDNS:NOK");       } altro { MDNS.addService("http", "tcp", 80); }        WiFiClientStarted = vero;     } altro      {     A0_ADCValue = analogRead(A0);     //Wir waren nicht erfolgreich, daher starten wir WPS, wenn WPS Assaggiatore di un A0 während des Reimposta gedrückt ist     se (A0_ADCValue > 499)       {         se(startWPS())            {             //ESP.wdtFeed();              delay(500);             WiFi.scollegare();             il WiFi.in modalità(WIFI_STA);             WiFi.iniziare(WiFi.SSID().c_str(), WiFi.psk().c_str());             //ESP.wdtFeed();              WiFiClientStarted = vero;           } altro           {             WiFiClientStarted = false;             WiFi.scollegare();           }       } il resto       {         WiFi.scollegare();       }    }    //WiFi.printDiag(di Serie); // Zu Debugzwecken fare clic.   ritorno WiFiClientStarted; 
}
// ******************* FINE di Funzioni di Gestione WiFi *************************************

// ******************* Funzioni di avviamento Store WiFi Credenziali di EEPROM ******************
bool loadCredentials() 
{
 bool RetValue;
 EEPROM.iniziare(512);
 EEPROM.ottenere(0,MyWiFiConfig);
 EEPROM.fine();
 se la (Stringa(MyWiFiConfig.ConfigValid) == "CT")    {     RetValue = vero;   } altro   {     RetValue = false; // Impostazioni WLAN nicht gefunden.   }   //ESP.wdtFeed();    ritorno RetValue; 
}

void saveCredentials() // Speichere WLAN credenziali auf EEPROM 
{   size_t io;   per (io = 0 ; ho < sizeof(MyWiFiConfig) ; i++) // Loeschen der alten Configurazione      {       EEPROM.scrivere(io, 0);       }   per (io = 0 ; ho < STANameLen  ; i++) // Loeschen der alten Konfiguration      {       MyWiFiConfig.WiFiPwd[io] = 0;       }   per (io = 0 ; ho < WiFiPwdLen ; ho++) // Loeschen der alten Konfiguration      {       MyWiFiConfig.APSTAName[ho] = 0;       }      temp = WiFi.SSID().c_str();   ho = temp.lunghezza();   temp.toCharArray(MyWiFiConfig.APSTAName,ho+1);    temp = WiFi.psk().c_str();   ho = temp.lunghezza();   temp.toCharArray(MyWiFiConfig.WiFiPwd,ho+1);   temp = "";      strncpy(MyWiFiConfig.ConfigValid , "CT", sizeof(MyWiFiConfig.ConfigValid) );    EEPROM.iniziare(512);   EEPROM.mettere(0, MyWiFiConfig);   EEPROM.commettere();   EEPROM.fine();   //ESP.wdtFeed(); 
}
// ******************* FINE Funzioni StoreCredentialsto EEPROM ***************************

// ******************* Funzioni di avviamento CardServices *************************************


void PCDHardReset()
{   digitalWrite(RST_PIN,BASSO);   ritardo(200);   digitalWrite(RST_PIN,ALTA);   mfrc522.PCD_Reset();   mfrc522.PCD_Init();                              // Initialisiere MFRC522 Lesemodul   mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); // Setzt Antenne auf max. Empfang   mfrc522.PCD_AntennaOn();
}

boolean CardAuthenticate(boolean ABKey, byte Settore,byte ikey[6])
{
const byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
byte statusA;
statusA = 0;
per (int una = 0; una < 6;una++)   {   chiave.keyByte[un] = ikey[un];   }   // Chiave A
se (ABKey)   {   statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, sectorkeytable[Settore], &chiave, &(mfrc522.uid));   se (statusA != MFRC522::STATUS_OK)     {     di Serie.println("ATAUTH:ERR_A");     return false;     }       }   // Tasto B   altro se (non ABKey)   {   statusA = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B,sectorkeytable[Settore], &chiave, &(mfrc522.uid));   se (statusA != MFRC522::STATUS_OK)     {     di Serie.println("ATAUTH:ERR_B");     return false;     }        }
return true;   }

// WriteData . utilizza la Variabile Globale DataBuffer per i Dati di Ritorno
booleano CardDataWrite(byte Settore,byte blocco di,byte valore[16])
{
del byte di stato;
byte writevector;
byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
writevector = Settore * 4 + blocco -1 ;
di (byte un = 0; un < 16; un++)   {   se (writevector ==  sectorkeytable[un])     {     // Serial.println("NAK");     return false;     }   }
stato = mfrc522.MIFARE_Write(writevector, valore, 16);
se (lo stato != MFRC522::STATUS_OK)   {   di Serie.println("ATPCD:W_ERR");   //Serial.println(mfrc522.GetStatusCodeName(status));   return false;   } else    {   // Serial.print("OK");   return true;   }   }

// Lettura Dati - utilizza la Variabile Globale DataBuffer per i Dati di Ritorno
booleano CardDataRead(byte Settore,byte blocco di)
{
byte statusi;
byte readvector;
const byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
byte di dimensioni = 18;
readvector = Settore * 4 + blocco -1 ;
di (byte un = 0; un < 16; un++)   {   se (readvector ==  sectorkeytable[una])     {      Serie.println("ATPCD:R_ERR");       return false;     }   }
statusi = mfrc522.MIFARE_Read(readvector, DataBuffer, &di una certa dimensione);
se (statusi != MFRC522::STATUS_OK)   {   Seriale.println(«ATPCD:R_ERR»);   ritornare falso;   } altro    {   ritornare vero;   }   }

boolean ResetCardToDefault()
{
byte ikey[16];
byte stato,io;
byte writevector;
può byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
writevector = sectorkeytable[USED_Sector];
se (CardAuthenticate(KEYB,USED_Sector,MiFareClassicKey.Key_B)) //Il settore Autenticate per SCRIVE l'accesso      {       per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; }           se (!(CardDataWrite(USED_Sector,1,DataBuffer))) { ritornare falso; }        per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; }          se (!(CardDataWrite(USED_Sector,2,DataBuffer))) { ritornare falso; }       per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; }          se (!(CardDataWrite(USED_Sector,3,DataBuffer))) { ritornare falso;}      }
per (byte io = 0; io <= 16; io++) { ikey[io] = 255; }  //Chiave d'Inadempienza di carico per tutti i Settori 
ikey[6] = 0xFF; //Installazione d'inadempienza per pezzettini di Accesso
ikey[7] = 0x07; // 
ikey[8] = 0x80; // 
ikey[9] = 0x69;    stato = mfrc522.MIFARE_Write(writevector, ikey, 16);
se (stato != MFRC522::STATUS_OK)   {   ritornare falso;   }
ritornare vero;   }

boolean SetSectorAccessControl (byte Settore,byte Akey[6],byte Bkey[6])
{
byte ikey[16];
byte stato;
byte writevector;
può byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
writevector = sectorkeytable[Settore];
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; //Condizioni di Accesso del blocco 0-3 di dati: Key B scrive / Key A Read
ikey[7] = 0x77; //KEY & B KEY & pezzettini di Acces Write:Key B / pezzettini di Key A Read Access
ikey[8] = 0x88; //Calcolatrice: http://calc.gmss.ru/Mifare1k/
ikey[9] = 0x69; //Valore fisso - > stregoneria di pratica d'inadempienza 69
ikey[10] = Bkey[0];
ikey[11] = Bkey[1];
ikey[12] = Bkey[2];
ikey[13] = Bkey[3];
ikey[14] = Bkey[4];
ikey[15] = Bkey[5];
stato = mfrc522.MIFARE_Write(writevector, ikey, 16);
se (stato != MFRC522::STATUS_OK)   {   Seriale.println(«ATPCD:W_KEY_ERR»);   ritornare falso;   }altro    {   ritornare vero;   }   }

boolean CheckforDefaultCardKey ()
{
byte tkey[6];
boolean CardResult; 
byte readvector;
byte statusi;
può byte sectorkeytable [16] = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63};
byte di una certa dimensione = 18;
per (byte io = 0; io <= 6; io++) { tkey[io] = 255; }  //Chiave d'Inadempienza di carico per tutti i Settori 
CardResult = vero;   se (!CardAuthenticate(KEYA,USED_Sector,tkey)) { CardResult = falso; };
readvector = sectorkeytable[USED_Sector];
statusi = mfrc522.MIFARE_Read(readvector, DataBuffer, &di una certa dimensione);
se (statusi != MFRC522::STATUS_OK) { CardResult = falso; } 
//se (! ((DataBuffer [7] = 0x07) & (DataBuffer [7] = 0x80))) {CardResult = falso;};
ritornare CardResult; 
}

boolean WriteNewMiFareClassicPICC ()   {   byte tkey[6];   byte io,a;   boolean CardResult;   se (CheckforDefaultCardKey())     {     per (io = 0; io <= 6; io++) { tkey[io] = 255; }  //Chiave d'Inadempienza di carico per tutti i Settori      per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; } //Respingenti non costanti chiari     CardResult = vero;            se (CardAuthenticate(KEYA,USED_Sector,tkey)) //Settore Autenticate       {       //Serial.println («Auth Sec 0 va bene»);        se (Cognome.lunghezza() > 15) { a = 15; } altro { a = Cognome.lunghezza();}       se (Cognome.lunghezza() > 0)         {         per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; }             per (io = 0; io <= a; io++) { DataBuffer[io] = Cognome[io]; }            se (!(CardDataWrite(USED_Sector,2,DataBuffer))) { CardResult = falso; } //Il settore 0 blocca 2 nomi dati con Chiave A scrivono         }       se (Givenname.lunghezza() > 15) { a = 15; } altro { a = Givenname.lunghezza(); }       se (Givenname.lunghezza() > 0)         {         per (io = 0; io <= 16; io++) { DataBuffer[io] = 0; }          per (io = 0; io <= a; io++) { DataBuffer[io] = Givenname[io]; }          se (!(CardDataWrite(USED_Sector,3,DataBuffer))) { CardResult = falso; } //Il settore 0 blocca 3 cognomi con Chiave A scrivono         }             se (!(SetSectorAccessControl (USED_Sector,MiFareClassicKey.Key_A,MiFareClassicKey.Key_B))) { CardResult = falso; }    //(Settore di byte, byte Akey [6], byte Bkey [6])       } altro {               CardResult = falso;              ritornare CardResult;              }        } altro {               CardResult = falso;              ritornare CardResult;              }          se (CardResult)        {        //Serial.println («PICC scritto»);       CardResult = vero;       }     altro        {        //Serial.println («PICC vuoto»);       CardResult = falso;       }     raccolto();       ritornare CardResult;   }


boolean ReadMiFareClassicPICC ()
{
boolean CardResult;
byte io,a ;
CardResult = vero;    se (CardAuthenticate(KEYA,USED_Sector,MiFareClassicKey.Key_A)) //Settore Autenticate con chiave LETTA A   {   Givenname = «aaaaaaaaaaaaaaaa»; //PlaceHolder   Cognome = «aaaaaaaaaaaaaaaa»; //PlaceHolder   per (io = 0; io < 18; io++) { DataBuffer[io] = 0; } //Respingenti non costanti chiari   se (CardDataRead(USED_Sector,2)) //Scelga il nome Dato di campo     {         per (io = 0; io < 16; io++) { Cognome[io] = lavoro a giornata(DataBuffer[io]);  }             } altro {             ritornare falso;            }     per (io = 0; io < 18; io++) { DataBuffer[io] = 0; } //Respingenti non costanti chiari     se (CardDataRead(USED_Sector,3)) //Scelga il Cognome di campo       {                per (io = 0; io < 16; io++) { Givenname[io] = lavoro a giornata(DataBuffer[io]); }              } altro {               ritornare falso;                 }      } altro      {      ritornare falso;     }
Seriale.stampa («ATAUTH_S»:);
Seriale.println (Cognome);
Seriale.stampa («ATAUTH_G»:);
Seriale.println (Givenname);
ritornare vero;
}

vuoto CardServer()
{
#define PCD_Poll_Interval 400
#define PCD_Watchdog_Interval 60000
se (millis() - PCD_ServiceCall_Handler >= PCD_Poll_Interval)    {    PCD_ServiceCall_Handler = millis();        se (mfrc522.PICC_IsNewCardPresent())   //PICC = carta di circuito integrato di prossimità = carta con chip elettronico senza contatto     {      mfrc522.PICC_ReadCardSerial();       raccolto();     //Differenziazione dopo tipo di mappa     //0x08 per 1K classico MIFARE     //0x18 per 4K classico MIFARE     //0x11 per PIÙ MIFARE     se (mfrc522.uid.sak == 0x08 || mfrc522.uid.sak == 0x18)       {       //INIZIO di MiFare_Classic_Processor (mfrc522.uid.sak);//spiegano Solo se Una mappa Classica Mifare prima del lettore è stata considerata.       byte tkey[6];        per (byte io = 0; io <= 6; io++) { tkey[io] = 255; }  //Chiave d'Inadempienza di carico per tutti i Settori        se(LearnNewCard) //la nuova mappa deve esser formata.         {           se (WriteNewMiFareClassicPICC()) { SetRGBLed(0,255,0,falso); } altro { SetRGBLed(255,0,0,falso); }         }       altro se (EraseCard)  //I dati di mappa devono esser estinti.         {           se (ResetCardToDefault()) { SetRGBLed(0,255,0,falso); } altro { SetRGBLed(255,0,0,falso); }         }             altro         {         se (ReadMiFareClassicPICC())            { //Mappa valida!           bool PinState= digitalRead(RELAIS_PIN);           PinState = !PinState;           digitalWrite(RELAIS_PIN, PinState);           SetRGBLed(0,255,0,falso);        //Verde condotto           } altro { SetRGBLed(255,0,0,falso); }               }       LearnNewCard = falso;                     //ARRESTO di MiFare_Classic_Processor (mfrc522.uid.sak);       } altro se (mfrc522.uid.sak == 0x00) //Ultraluce di Mifare       {         SetRGBLed(255,0,0,falso);       } altro       {         SetRGBLed(255,0,0,falso);         //Serial.print («Tipo di PICC non sostenuto. Batta a macchina»:);          //Serial.println (mfrc522.uid.sak);//ampliamento: forse altri tipi di mappa       }     mfrc522.PCD_StopCrypto1();     mfrc522.PICC_HaltA();     ritardo(2000);     SetRGBLed(0,0,255,falso);        //Il lettore Azzurro a colori condotto è in stato fondamentale     }   }   se (millis() - PCD_WatchDog_Handler >= PCD_Watchdog_Interval)    {    PCD_WatchDog_Handler = millis();    Risultato = mfrc522.PCD_PerformSelfTest();    raccolto();    mfrc522.PCD_Init();                       //Inizializzi il modulo di lettura MFRC522 ancora una volta    mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); //Se aerial mette su ricevuta di max.    mfrc522.PCD_AntennaOn();     raccolto();    se (!(Risultato))      {       PCDHardReset();       Seriale.println(«ATPCD:ERR_H»);     }    }   }

//i ******************* fermano Funzioni CardServices *************************************


 
vuoto cappio()  //Cappio principale
{   CardServer();          //Mappi di lavoro di lettori su richieste di informazioni specifiche   raccolto();    server.handleClient(); //Le richieste di informazioni di server Web lavorano    //ESP.wdtFeed ();//il Cane da guardia ritorna indietro. Disattivi con «wdt_disable ()»;
}

 

WLAN di dati connettenti sono mantenuti, perché abbiamo registrato questo nello schizzo precedente in non la memoria breve.

Come, comunque, fa adesso l'autenticazione della funzione della mappa adesso, comunque, adesso?

Semplicisticamente detto, il modulo del lettore di mappa prova con la sospensione di una mappa del tipo il Classico di MiFare (questo diventa un approccio controllato) un settore che è piacevole a leggersi solo con chiave valida per leggere.

Se l'azione è di successo, i campi di nome Dati il nome e cognome sono scelti e la mappa è riconosciuta come valida. (Il relé è cambiato) Essere l'autenticazione con successo o la chiave sbagliata non è usato, la mappa è abbassata come invalido.

Dalla differenziazione tra «mappa valida o l'invalido di mappa» in questo segno i vantaggi seguenti si alzano per noi:

Parecchie mappe possono avere diritto nello stesso momento in un lettore senza cui ogni mappa al lettore deve esser già annunciata nell'approccio da UUID.

Parecchi lettori di mappa con una mappa possono esser serviti nello stesso momento senza ogni lettore di mappa che ogni mappa già nell'approccio da UUID conosce.

«I cerchi di autorizzazione» possono esser formati da variazione della definizione di settore o il materiale chiave.

 

Adesso provvediamo la nostra prima mappa di autorizzazione. Inoltre andiamo, dopo richiesta di connessione sul menù indicano «PICC», poi provvedono la nuova mappa „“ e lo cliccano. Vediamo la parte seguente:

Diamo un nome dato e un cognome nei campi voluti, e premiamo il distintivo „nuovi Smartcard provvedono alle necessità “

Il CONDOTTO diventa giallo. Adesso teniamo un VUOTO!! La mappa di Classico di Mifare prima del lettore e brevemente aspetta al CONDOTTO diventa verde. È stato questo! D'ora in poi possiamo usare questa mappa adesso come una mappa autorizzata nel nostro lettore.

Se vogliamo fare questo invalido di mappa, andiamo, dopo richiesta di connessione sul menù indicano PICC, allora sotto „gioca a carte lo estinguono “e cliccano. - Dall'annuncio:

se rimaniamo prima di mappa autorizzata di nuovo prima del lettore. Questo è invalido in seguito.

Molto divertimento copiandoci fino alla vicina parte.

Esp-8266Per arduinoProjekte für fortgeschritteneCasa intelligente

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert

Post di blog consigliati

  1. Installa ESP32 ora dal gestore del consiglio di amministrazione
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - Programmazione ESP tramite WLAN