Salutări!
A trecut mult timp de când a apărut API-ul pentru amprente pentru Android, există numeroase eșantioane împrăștiate de cod cu privire la implementarea și utilizarea acestuia, dar pe Habr, din anumite motive, acest subiect a fost bypassed. După părerea mea, este timpul să corectăm această neînțelegere.
Toți sunt interesați să ceară o pisică.
Cel mai scurt program educațional
Deci, ce este API-ul Fingerprint?
API permite utilizatorului să se autentifice cu amprenta sa, evident.
Pentru a lucra cu senzorul, API ne oferă FingerprintManager. destul de ușor să învețe.
Cum se utilizează?
Dar acest lucru este mai interesant.
Aproape oriunde este necesară autentificarea parolei, este posibil să se securizeze autentificarea prin amprentă digitală.
Imaginați-vă o aplicație constând din LoginActivity și MainActivity. La pornire, ajungem la ecranul de conectare, introduceți codul PIN, accesați datele. Dar dorim să înlocuim intrarea cu codul PIN la intrare prin amprentă digitală.
Apropo, nu obținem un înlocuitor pe deplin, putem salva numai utilizatorul de la introducerea manuală a unui cod PIN, înlocuind codul PIN memorat anterior (adică aplicația client-server în care doriți să trimiteți serverul de parolă).
Să începem.
Unde este senzorul?
Pentru a începe să obțineți profit din noul API, primul pas este să adăugați permisiunea în manifest:
Desigur, puteți utiliza API-ul Fingerprint numai pe dispozitive care îl acceptă: în consecință, acestea sunt dispozitive Android 6+ cu senzor.
Compatibilitatea poate fi ușor verificată utilizând metoda:
FingerprintManagerCompat este un wrapper convenabil pentru FingerprintManager obișnuit. care simplifică verificarea compatibilității dispozitivului, încapsulând verificarea versiunii API. În acest caz, isHardwareDetected () returnează false. dacă API este sub 23.
Apoi, trebuie să înțelegem dacă senzorul este gata de utilizare. Pentru a face acest lucru, definim enum states:
Și să folosim această metodă:
Codul este suficient de banal. O mică neînțelegere poate provoca un moment când verificăm dacă dispozitivul este blocat. Avem nevoie de acest test, deoarece, deși Android nu permite adăugarea amprentelor digitale la un dispozitiv neprotejat, unii producători îl ocolește, deci nu va face rău pentru a fi sigur.
Stări diferite pot fi folosite pentru a da utilizatorului posibilitatea de a înțelege ce se întâmplă și de al îndruma pe calea adevărată.
Pregătirea
Așadar, fără a ne concentra asupra verificării valabilității codului PIN, vom estima următoarea logică simplificată a acțiunilor:
- Utilizatorul introduce un cod PIN dacă SensorState.READY. apoi salvăm codul PIN, executați MainActivity.
- Reporniți aplicația dacă SensorState.READY. apoi citiți amprenta, obțineți codul PIN, simulați intrarea, executați MainActivity.
Schema ar fi suficient de simplă, dacă nu de un singur lucru: Google recomandă cu tărie să nu păstrați datele private ale utilizatorilor în mod clar. Prin urmare, avem nevoie de un mecanism de criptare și decriptare pentru, respectiv, conservare și utilizare. Vom face asta.
Ce avem nevoie pentru a cripta și a decripta:
- Tastatură protejată.
- Cheia criptografică.
- Cod cifrat
Pentru a lucra cu amprentele, sistemul ne oferă propriul magazin de chei - "AndroidKeyStore" și garantează protecția împotriva accesului neautorizat. Vom folosi:
Este necesar să acceptați, să înțelegeți și să iertați că magazinul de chei stochează numai cheile criptografice. Parolele, codurile PIN și alte date private nu pot fi stocate acolo.
Avem două opțiuni pentru chei: o cheie simetrică și o pereche de chei publice și private. Din considerentele lui UX, folosim o pereche. Acest lucru ne va permite să separăm intrarea imprimării de criptarea codului PIN.
Vom primi cheile de la magazinul de chei, dar mai întâi trebuie să le punem acolo. Pentru a crea o cheie, utilizați generatorul.
Atunci când inițializăm, specificăm ce tastă vor fi cheile generate și la care algoritmul este destinat cheii.
Aceeași generație are loc după cum urmează:
Aici trebuie să fii atenți la două locuri:
- KEY_ALIAS este pseudonimul cheii, prin care îl vom scoate din chestor, de la psf-urile obișnuite.
- .setUserAuthenticationRequired (adevărat) - acest steag indică faptul că de fiecare dată când trebuie să folosim cheia, va trebui să ne confirmăm, în cazul nostru, folosind o amprentă digitală.
Verificați prezența cheii după cum urmează:
Cod cifrat
Criptarea și decriptarea în Java este gestionată de obiectul Cipher. Inițializați-l:
Momentul ad-hoc al argumentului este șirul transformării, care include algoritmul. modul de amestecare și adăugare.
După ce am primit cifra. trebuie să o pregătiți pentru muncă.
La generarea cheii, am indicat că o vom folosi doar pentru criptare și decriptare. În consecință, Cipher va fi, de asemenea, în aceste scopuri:
unde initDecodeCipher () și initEncodeCiper () sunt:
Nu este greu de observat că cifrul de criptare este oarecum mai dificil de inițializat. Acesta este un escroc al companiei Google, esența căruia cheia publică necesită confirmarea de către utilizator. Noi ocolim această cerință cu ajutorul unei impresii cheie (cârjă, da).
Moment cu KeyPermanentlyInvalidatedException - dacă din anumite motive cheia nu poate fi utilizată, această excepție este declanșată. Motivele posibile includ adăugarea unei imprimări noi la una existentă, schimbarea sau eliminarea completă a blocării. Apoi, cheia nu mai are sens să stocheze și o ștergem.
O metodă care colectează întregul lanț de formare:
Criptare și decriptare
Să descriem o metodă care criptează șirul de argument:
Ca rezultat, obținem Base64 - un șir care poate fi stocat în condiții de siguranță în preferințele aplicației.
Pentru a decoda același lucru, folosim următoarea metodă:
Opa, pe intrarea pe care o primește nu numai șirul criptat, ci și obiectul Cipher.
De unde a venit, va deveni clar mai târziu.
Degetul greșit
Pentru a utiliza în sfârșit senzorul, trebuie să utilizați metoda FingerprintManagerCompat:
Hendler și steaguri, acum nu avem nevoie, semnalul este utilizat pentru a anula modul cititor de amprente (minimizată cerere, de exemplu), callbacks returnează rezultatul unei anumite lecturi, dar peste kriptoobektom mai multe detalii.
În acest caz, CryptoObject este folosit ca un înveliș pentru Cipher. Pentru ao obține, utilizați metoda:
Așa cum am spus, rezultatele citirii senzorului pe care o primim în metodele de colaționare. Iată cum arată:
În cazul recunoașterii reușite, obținem AuthenticationResult. din care putem obține obiectul Cipher cu cheia deja verificată:
Vă mulțumesc pentru atenție.