L’autenticazione delle impronte digitali utilizza il sensore tattile integrato in molti dispositivi Android per identificare l’utente e fornire l’accesso sia al dispositivo che alle funzionalità dell’applicazione come le opzioni di pagamento in-app. L’implementazione dell’autenticazione delle impronte digitali è un processo a più fasi che può, all’inizio, sembrare travolgente. Quando si scompone in singole fasi, tuttavia, il processo diventa molto meno complesso. In termini di base, l’autenticazione delle impronte digitali è principalmente una questione di crittografia che coinvolge una chiave, un cifrario per eseguire la crittografia e un gestore di impronte digitali per gestire il processo di autenticazione.
Questo capitolo fornisce sia una panoramica dell’autenticazione delle impronte digitali che un dettagliato tutorial passo dopo passo che dimostra un approccio pratico all’implementazione.
Una panoramica dell’autenticazione delle impronte digitali
Ci sono essenzialmente 10 passi per implementare l’autenticazione delle impronte digitali in un’applicazione Android. Questi passi possono essere riassunti come segue:
1. Richiedere l’autorizzazione per l’autenticazione delle impronte digitali all’interno del file Manifest del progetto.
2. Verificare che lo schermo di blocco del dispositivo su cui è in esecuzione l’applicazione sia protetto da un PIN, un modello o una password (le impronte digitali possono essere registrate solo su dispositivi in cui lo schermo di blocco è stato protetto).
3. Verificare che almeno un’impronta digitale sia stata registrata sul dispositivo.
4. Creare un’istanza della classe FingerprintManager.
5. Usare un’istanza di Keystore per ottenere l’accesso al contenitore Keystore di Android. Questa è un’area di memorizzazione utilizzata per la conservazione sicura delle chiavi crittografiche sui dispositivi Android.
6. Generare una chiave di crittografia utilizzando la classe KeyGenerator e memorizzarla nel contenitore Keystore.
7. Inizializzare un’istanza della classe Cipher usando la chiave generata nel passo 5.
8. Usare l’istanza Cipher per creare un CryptoObject e assegnarlo all’istanza FingerprintManager creata nel passo 4.
9. Chiamate il metodo authenticate dell’istanza FingerprintManager.
10. Implementare i metodi per gestire le callback innescate dal processo di autenticazione. Fornire l’accesso al contenuto protetto o alla funzionalità al completamento di un’autenticazione riuscita.
Ognuno dei passi sopra descritti sarà coperto in modo più dettagliato durante il tutorial delineato nel resto di questo capitolo.
Creazione del progetto di autenticazione delle impronte digitali
Iniziare questo esempio lanciando l’ambiente Android Studio e creando un nuovo progetto, inserendo FingerprintDemo nel campo Nome applicazione e ebookfrenzy.com come impostazione Company Domain prima di cliccare sul pulsante Next.
Nella schermata dei fattori di forma, attiva l’opzione Phone and Tablet e imposta l’impostazione SDK minimo su API 23: Android 6.0 (Marshmallow). Continua attraverso le schermate di configurazione, richiedendo la creazione di un’attività vuota chiamata FingerprintDemoActivity con un layout corrispondente chiamato activity_fingerprint_demo.
Configurazione dell’autenticazione dell’impronta digitale del dispositivo
L’autenticazione dell’impronta digitale è disponibile solo sui dispositivi che contengono un sensore tattile e sui quali sono stati effettuati i passi di configurazione appropriati per proteggere il dispositivo e registrare almeno un’impronta digitale. Per i passaggi sulla configurazione di una sessione dell’emulatore per testare l’autenticazione delle impronte digitali, fai riferimento al capitolo intitolato Utilizzo e configurazione dell’emulatore Android Studio 2 AVD.
Per configurare l’autenticazione delle impronte digitali su un dispositivo fisico inizia aprendo l’app Impostazioni e selezionando l’opzione Sicurezza. All’interno della schermata delle impostazioni di sicurezza, selezionate l’opzione Impronta digitale. Nella schermata di informazioni risultante, clicca sul pulsante Continua per procedere alla schermata di configurazione delle impronte digitali. Prima che la sicurezza delle impronte digitali possa essere abilitata, è necessario configurare un metodo di sblocco dello schermo di backup (come un numero PIN). Cliccare sul pulsante Set Up Screen Lock se lo schermo di blocco non è già protetto e seguire i passi per configurare la sicurezza tramite PIN, modello o password.
Con lo schermo di blocco protetto, procedere alla schermata di rilevamento delle impronte digitali e toccare il sensore quando richiesto (Figura 62-1), ripetendo il processo per aggiungere altre impronte digitali, se necessario.
Figura 62-1
Aggiungimento del permesso per le impronte digitali al file manifesto
L’autenticazione delle impronte digitali richiede che l’app richieda il permesso USE_FINGERPRINT all’interno del file manifesto del progetto. All’interno della finestra dello strumento Android Studio Project individua e modifica l’app -> manifesti -> file AndroidManifest.xml per aggiungere la richiesta di autorizzazione come segue:
Scaricare l’icona dell’impronta digitale
Google fornisce un’icona standard (Figura 62-2) che deve essere visualizzata ogni volta che un’app richiede l’autenticazione da parte di un utente.
Figura 62-2
Una copia di questa icona può essere scaricata dal seguente URL:
Apri il navigatore del sistema operativo, seleziona l’immagine appena scaricata e premi Ctrl-C (Cmd-C su Mac OS X) per copiare il file. Torna in Android Studio, clicca con il tasto destro del mouse sulla cartella app -> res -> drawable e seleziona l’opzione di menu Paste per aggiungere una copia del file immagine al progetto. Quando appare la finestra di dialogo Copy, clicca sul pulsante OK per usare le impostazioni predefinite.
Progettazione dell’interfaccia utente
Nell’interesse di mantenere l’esempio il più semplice possibile, gli unici elementi dell’interfaccia utente saranno una TextView e una ImageView. Individua e seleziona il file di risorse di layout activity_fingerprint_demo.xml per caricarlo nello strumento Designer. Una volta caricato, cancella l’oggetto TextView di esempio, trascina e rilascia un oggetto ImageView dal pannello e posizionalo al centro della tela del layout.
Nel pannello Properties, individuate l’attributo src, cliccate nel campo di testo corrispondente seguito dal pulsante evidenziato in Figura 62-3 per visualizzare la finestra di dialogo Resources:
Figura 62-3
Dal pannello di sinistra della finestra di dialogo selezionate l’opzione Drawable. All’interno del pannello principale, inserite ic_fp nella casella di ricerca come illustrato nella Figura 62 4 per individuare l’icona dell’impronta digitale. Selezionate l’icona dalla finestra di dialogo e cliccate su OK per assegnarla all’oggetto ImageView.
Figura 62-4
Localizzate l’oggetto Large Text dalla palette e trascinatelo in modo che sia posizionato sotto l’oggetto ImageView. Fate doppio clic sull’oggetto e cambiate il testo in modo che legga “Touch Sensor”. Usate l’icona della lampadina per estrarre la stringa in una risorsa chiamata touch_sensor.
Al completamento dei passi precedenti il layout dovrebbe corrispondere a quello mostrato nella Figura 62-5:
Figura 62-5
Accedere ai servizi Keyguard e Fingerprint Manager
L’autenticazione delle impronte digitali fa uso di due servizi di sistema, il KeyguardManager e il FingerprintManager. Modifica il metodo onCreate che si trova nel file FingerprintDemoActivity.java per ottenere i riferimenti a questi due servizi come segue:
package com.ebookfrenzy.fingerprintdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.app.KeyguardManager;import android.hardware.fingerprint.FingerprintManager;public class FingerprintDemoActivity extends AppCompatActivity { private FingerprintManager fingerprintManager; private KeyguardManager keyguardManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fingerprint_demo); keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE); }}
Checking the Security Settings
Prima in questo capitolo sono stati fatti dei passi per configurare il lock screen e registrare le impronte digitali sul dispositivo o emulatore su cui l’applicazione verrà testata. È importante, tuttavia, includere del codice difensivo nell’app per assicurarsi che questi requisiti siano stati soddisfatti prima di tentare l’autenticazione delle impronte digitali. Questi passaggi saranno eseguiti all’interno del metodo onCreate che risiede nel file FingerprintDemoActivity.java, facendo uso dei servizi Keyguard e Fingerprint manager. Si noti che è stato aggiunto anche del codice per verificare che il permesso USE_FINGERPRINT sia stato configurato per l’app:
Le modifiche al codice di cui sopra iniziano utilizzando il gestore Keyguard per verificare che sia stato configurato un metodo di sblocco dello schermo di backup (in altre parole un PIN o un altro metodo di autenticazione può essere utilizzato come alternativa all’autenticazione dell’impronta digitale per sbloccare lo schermo). Nel caso in cui lo schermo di blocco non sia protetto, il codice segnala il problema all’utente e ritorna dal metodo.
Il gestore delle impronte digitali viene quindi utilizzato per verificare che almeno un’impronta digitale sia stata registrata sul dispositivo, ancora una volta segnalando il problema e tornando dal metodo se necessario.
Accedere all’Android Keystore e al KeyGenerator
Parte del processo di autenticazione delle impronte digitali comporta la generazione di una chiave di crittografia che viene poi memorizzata in modo sicuro sul dispositivo utilizzando il sistema Android Keystore. Prima che la chiave possa essere generata e memorizzata, l’app deve prima ottenere l’accesso al Keystore. Un nuovo metodo chiamato generateKey sarà ora implementato all’interno del file FingerprintDemoActivity.java per eseguire i compiti di generazione e memorizzazione della chiave. Inizialmente, solo il codice per accedere al Keystore sarà aggiunto come segue:
Un riferimento al Keystore è ottenuto chiamando il metodo getInstance della classe Keystore e passando attraverso l’identificatore del contenitore standard del keystore Android (“AndroidKeyStore”). Il prossimo passo del tutorial sarà quello di generare una chiave utilizzando il servizio KeyGenerator. Prima di generare questa chiave, bisogna aggiungere del codice per ottenere un riferimento a un’istanza del KeyGenerator, passando come argomenti il tipo di chiave da generare e il nome del contenitore Keystore in cui la chiave deve essere salvata:
Generating the Key
Ora che abbiamo un riferimento al contenitore Keystore Android e un’istanza del KeyGenerator, il prossimo passo è generare la chiave che verrà usata per creare un cifrario per il processo di crittografia. Rimanendo all’interno del file FingerprintDemoActivity.java, aggiungete questo nuovo codice come segue:
Le modifiche di cui sopra richiedono qualche spiegazione. Dopo aver importato una serie di moduli aggiuntivi, il codice dichiara una variabile stringa che rappresenta il nome (in questo caso “example_key”) che verrà utilizzato quando si memorizza la chiave nel contenitore Keystore.
Poi, il contenitore keystore viene caricato e il KeyGenerator inizializzato. Questo processo di inizializzazione fa uso della classe KeyGenParameterSpec.Builder per specificare il tipo di chiave da generare. Questo include il riferimento al nome della chiave, la configurazione della chiave in modo che possa essere usata sia per la crittografia che per la decrittografia e l’impostazione di vari parametri di crittografia. La chiamata al metodo setUserAuthenticationRequired configura la chiave in modo che l’utente debba autorizzare ogni uso della chiave con un’autenticazione tramite impronta digitale. Una volta che il KeyGenerator è stato configurato, viene utilizzato per generare la chiave attraverso una chiamata al metodo generateKey dell’istanza.
Inizializzazione del cifrario
Ora che la chiave è stata generata, il passo successivo è quello di inizializzare il cifrario che verrà utilizzato per creare l’istanza cifrata FingerprintManager.CryptoObject. Questo CryptoObject sarà, a sua volta, utilizzato durante il processo di autenticazione delle impronte digitali. La configurazione del cifrario comporta l’ottenimento di un’istanza Cipher e la sua inizializzazione con la chiave memorizzata nel contenitore Keystore. Aggiungete un nuovo metodo chiamato cipherInit al file FingerprintDemoActivity.java per eseguire questi compiti:
Il metodo getInstance della classe Cipher viene chiamato per ottenere un’istanza Cipher che viene successivamente configurata con le proprietà richieste per l’autenticazione dell’impronta digitale. La chiave generata in precedenza viene quindi estratta dal contenitore Keystore e utilizzata per inizializzare l’istanza Cipher. Gli errori vengono gestiti di conseguenza e viene restituito un risultato vero o falso in base al successo o meno del processo di inizializzazione del cifrario.
Il lavoro è ora completo su entrambi i metodi generateKey e cipherInit. Il prossimo passo è modificare il metodo onCreate per chiamare questi metodi e, in caso di successo dell’inizializzazione del cifrario, creare un’istanza di CryptoObject.
Creazione dell’istanza di CryptoObject
Rimanendo nel file FingerprintDemoActivity.java, modificare il metodo onCreate per chiamare i due metodi appena creati e generare il CryptoObject come segue:
Il compito finale del progetto è quello di implementare una nuova classe per gestire l’effettiva autenticazione delle impronte digitali.
Implementazione della classe Fingerprint Authentication Handler
Finora in questo capitolo la maggior parte del lavoro ha riguardato la preparazione dell’autenticazione delle impronte digitali in termini di chiave, cifra e oggetto crypto. L’autenticazione vera e propria viene attivata tramite una chiamata al metodo authenticate dell’istanza FingerprintManager. Questa chiamata al metodo, tuttavia, innescherà uno dei numerosi eventi di callback a seconda del successo o del fallimento dell’autenticazione. Sia la chiamata al metodo authenticate che i metodi di callback devono essere implementati in una classe che estende la classe FingerprintManager.AuthenticationCallback. Tale classe deve ora essere aggiunta al progetto.
Navigate fino alla voce app -> java -> com.ebookfrenzy.fingerprintdemo nella finestra dello strumento Android Studio Project e cliccate con il tasto destro del mouse. Dal menu risultante, seleziona l’opzione New -> Java Class per visualizzare la finestra di dialogo Create New Class. Dai un nome alla classe FingerprintHandler e clicca sul pulsante OK per creare la classe.
Modifica il nuovo file di classe in modo che estenda FingerprintManager.AuthenticationCallback, importi alcuni moduli aggiuntivi e implementi un metodo costruttore che permetta di passare il contesto dell’applicazione quando viene creata un’istanza della classe (il contesto sarà usato nei metodi di callback per notificare all’utente lo stato dell’autenticazione):
package com.ebookfrenzy.fingerprintdemo;import android.Manifest;import android.content.Context;import android.content.pm.PackageManager;import android.hardware.fingerprint.FingerprintManager;import android.os.CancellationSignal;import android.support.v4.app.ActivityCompat;import android.widget.Toast;public class FingerprintHandler extends FingerprintManager.AuthenticationCallback { private CancellationSignal cancellationSignal; private Context appContext; public FingerprintHandler(Context context) { appContext = context; }}
Poi deve essere aggiunto un metodo che può essere chiamato per iniziare l’autenticazione dell’impronta digitale. Quando viene chiamato, questo metodo dovrà essere passato alle istanze di FingerprintManager e CryptoObject. Chiamate questo metodo startAuth e implementatelo nel file di classe FingerprintHandler.java come segue (notate che è stato aggiunto anche del codice per controllare ancora una volta che l’autorizzazione per le impronte digitali sia stata concessa):
Poi, aggiungete i metodi handler di callback, ognuno dei quali è implementato per mostrare un messaggio di brindisi che indica il risultato dell’autenticazione delle impronte digitali:
Il compito finale prima di testare il progetto è di modificare il metodo onCreate in modo che crei una nuova istanza della classe FingerprintHandler e chiami il metodo startAuth. Editate il file FingerprintDemoActivity.java e modificate la fine del metodo onCreate in modo che si legga come segue:
Testare il progetto
Con il progetto ora completo eseguire l’applicazione su un dispositivo fisico Android o una sessione dell’emulatore. Una volta in esecuzione, toccare il sensore di impronte digitali o utilizzare il pannello di controllo esteso all’interno dell’emulatore per simulare un tocco di impronte digitali come descritto nel capitolo intitolato Utilizzo e configurazione dell’emulatore AVD di Android Studio 2. Supponendo che venga rilevata un’impronta digitale registrata, apparirà un messaggio di brindisi che indica un’autenticazione riuscita, come mostrato nella Figura 62-6:
Figura 62-6
Fermate l’applicazione in esecuzione e rilanciatela, questa volta usando un’impronta digitale non registrata per tentare l’autenticazione. Questa volta dovrebbe apparire un messaggio di brindisi che indica che l’autenticazione non è riuscita.
Sommario
L’autenticazione dell’impronta digitale in Android è un processo in più fasi che inizialmente può sembrare complesso. Quando si scompone in singoli passi, tuttavia, il processo diventa più chiaro. L’autenticazione delle impronte digitali coinvolge l’uso di chiavi, cifrari e memorizzazione delle chiavi combinati con le caratteristiche della classe FingerprintManager. Questo capitolo ha fornito un’introduzione a questi passaggi e ha lavorato attraverso la creazione di un progetto applicativo di esempio volto a mostrare l’implementazione pratica dell’autenticazione delle impronte digitali all’interno di Android.