SAMSUNG_082020 SAMSUNG_082020 SAMSUNG_082020 Advertisement

Naučte sa vyvíjať Android aplikácie – snímanie odtlačkov prstov

1

Niektoré aplikácie si vyžadujú autentifikáciu. Nemusí to byť hneď banková aplikácia, ale akákoľvek aplikácia, ktorá pracuje s citlivými údajmi.  Identifikácia pomocou odtlačkov prstov je viacstupňový proces, ktorý je implementovaný na úrovni operačného systému. Údaje o vzoroch na porovnávanie odtlačkov sú uložené zašifrovane. Samozrejme overenie pomocou odtlačku prsta je dostupné len v zariadeniach, ktoré obsahujú snímač a na ktorých bola nastavená konfigurácie zabezpečenia a nasnímaný a uložený aspoň jeden odtlačok prsta. 

Overovanie odtlačkov prstov je podporované je od verzie  API 23: Android 6.0 (Marshmallow), takže pri vytváraní projektu musíte nastaviť verziu Android 6.0, alebo vyššu.

Ak chcete nakonfigurovať overovanie odtlačkov prstov na fyzickom zariadení, spustite Nastavenie a vyberte možnosť prihlasovania pomocou odtlačkov prstov. Najskôr je potrebné nakonfigurovať alternatívnu autentifikácie, napríklad pomocou PIN kódu. Následne nasnímajte jeden, alebo viac vzorov odtlačkov vašich prstov.

Do aplikácie, ktorá bude využívať tento spôsob autentifikácie je potrebné do aplikačného manifestu pridať riadok

<uses-permission android:name="android.permission.USE_FINGERPRINT" />

Android aplikácie by mali akceptovať štandardy a jedným z nich je odporúčaná ikona na autentifikáciu pomocou odtlačku prsta. Vhodný obrázok vložte do zložky Drawable.

Naša aplikácia bude mať v layoute hlavnej aktivity iba túto ikonu aby používateľ vedel, že sa od neho vyžaduje prihlásenie odtlačkom prsta

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <ImageView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:scaleType="fitCenter"
        android:src="@drawable/ikona_odtlacok"/>
</RelativeLayout>

Overovanie odtlačku využíva dve systémové služby KeyguardManager a FingerprintManager. 

keyguardManager =
       (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
fingerprintManager =
       (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);

Následne je potrebné overiť, či je autentifikácia pomocou odtlačkov prstov povolená, a či je pridaný aspoň jeden odtlačok. Overovanie odtlačkov prstov zahŕňa generovanie šifrovacieho kľúča, ktorý je bezpečne uložený v zariadení v systémovom úložisku kľúčov. Aplikácia potrebuje povolenie na prístup k úložisku kľúčov. 

protected void generateKey() {
   try {
       keyStore = KeyStore.getInstance("AndroidKeyStore");
   } catch (Exception e) {
    e.printStackTrace();
   }

Nasleduje generovanie kľúča pomocou služby KeyGenerator. Pred generovaním je potrebné získať odkaz na inštanciu KeyGenerator.

try {
     keyGenerator = KeyGenerator.getInstance(
              KeyProperties.KEY_ALGORITHM_AES,
              "AndroidKeyStore");
  } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
      throw new RuntimeException(
        "Probblém inštancie KeyGenerator", e);
  }

Teraz môže aplikácia vygenerovať kľúč

try {
        keyStore.load(null);
        SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return true;
    } catch (KeyPermanentlyInvalidatedException e) {
        return false;
    } catch (KeyStoreException | CertificateException
            | UnrecoverableKeyException | IOException
            | NoSuchAlgorithmException | InvalidKeyException e) {
        throw new RuntimeException("Cipher ERR", e);
    }

Do reťazcovej premennej "my_key" sa zapíše kľúč, ktorý je v kontajneri úložiska kľúčov. Tento kľúč bude použitý pre šifrovanie a dešifrovanie, a nastavenie rôznych parametrov šifrovania. Šifrovanie rieši CryptoObject v metóde cipherInit().

Ak to zosumarizujeme, zatiaľ sme popisovali prípravné fázy, získavanie a vytváranie objektov na šifrovanie a s ním súvisiace kľúče. Na prvý pohľad to vyzerá zložité ale je to pomerne jednoduchá a navyše logická postupnosť krokov. Teraz však vstupujeme do finále, ktorým je autentifikácia pomocou volania metódy authenticate inštancie FingerprintManager. Toto volanie spustí ešte zložitejšíu postupnosť krokov, ktorú však nemusíme riešiť, pretože sa realizuje na úrovni operačného systému. 

Výsledkom v prípade úspechu aj neúspechu je callback. Metódy je potrebné implementovať v triede, ktorá rozširuje triedu FingerprintManager.AuthenticationCallback. V našom príklade sme rešpektovali tradícii, presnejšie popis autentifikácie na https://developer.android.com a triedu sme nazvali FingerprintHandler. 

Kompletný kód triedy FingerprintHandler. 

package com.example.odtlacokprsta;
 
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.widget.Toast;
 
import androidx.core.app.ActivityCompat;
 
public class FingerprintHandler extends
        FingerprintManager.AuthenticationCallback {
 
    private CancellationSignal cs;
    private Context aContext;
 
    public FingerprintHandler(Context context) {
        aContext = context;
    }
 
    public void startAuth(FingerprintManager fm,
                          FingerprintManager.CryptoObject cryptoObject) {
 
        cs = new CancellationSignal();
 
        if (ActivityCompat.checkSelfPermission(aContext,
                Manifest.permission.USE_FINGERPRINT) !=
                PackageManager.PERMISSION_GRANTED) {
            return;
        }
        fm.authenticate(cryptoObject, cs, 0, this, null);
    }
 
    @Override
    public void onAuthenticationError(int errMsgId,
                                      CharSequence errString) {
        Toast.makeText(aContext,
                "Chyba autentifikácie\n" + errString,
                Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onAuthenticationHelp(int helpMsgId,
                                     CharSequence helpString) {
        Toast.makeText(aContext,
                "Nápoveda\n" + helpString,
                Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onAuthenticationFailed() {
        Toast.makeText(aContext,
                "Chyba autentifikácie.",
                Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onAuthenticationSucceeded(
            FingerprintManager.AuthenticationResult result) {
 
        Toast.makeText(aContext,
                "Autentifikácia OK.",
                Toast.LENGTH_LONG).show();
    }
 
}

A teraz kód hlavnej aktivity. Pre úplnosť uvádzame aj zoznam referencií

package com.example.odtlacokprsta;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
 
import android.Manifest;
import android.app.KeyguardManager;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.widget.Toast;
 
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
 
 
 
public class MainActivity extends AppCompatActivity {
 
    private static final String KEY_NAME = "my_key";
    private FingerprintManager fm;
    private KeyguardManager km;
    private KeyStore keyStore;
    private KeyGenerator kg;
    private Cipher cipher;
    private FingerprintManager.CryptoObject co;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
        fm = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
 
        if (!km.isKeyguardSecure()) {
            Toast.makeText(this,
                    "Nakonfigurujte odtlačok prsta v Nastavení",
                    Toast.LENGTH_LONG).show();
            return;
        }
 
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.USE_FINGERPRINT) !=
                PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this,
                    "Autentifikácia odtlačkom nie je povolená",
                    Toast.LENGTH_LONG).show();
            return;
        }
 
        if (!fm.hasEnrolledFingerprints()) {
            Toast.makeText(this,
                    "Zaregistrujte aspoň jeden odtlačok",
                    Toast.LENGTH_LONG).show();
            return;
        }
 
        generateKey();
 
        if (cipherInit()) {
            co = new FingerprintManager.CryptoObject(cipher);
            FingerprintHandler helper = new FingerprintHandler(this);
            helper.startAuth(fm, co);
        }
    }
 
    public boolean cipherInit() {
        try {
            cipher = Cipher.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES + "/"
                            + KeyProperties.BLOCK_MODE_CBC + "/"
                            + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        } catch (NoSuchAlgorithmException |
                NoSuchPaddingException e) {
            throw new RuntimeException("Cipher ERR", e);
        }
 
        try {
            keyStore.load(null);
            SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                    null);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return true;
        } catch (KeyPermanentlyInvalidatedException e) {
            return false;
        } catch (KeyStoreException | CertificateException
                | UnrecoverableKeyException | IOException
                | NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("Cipher ERR", e);
        }
    }
 
    protected void generateKey() {
        try {
            keyStore = KeyStore.getInstance("AndroidKeyStore");
        } catch (Exception e) {e.printStackTrace();}
 
        try {
            kg = KeyGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES,
                    "AndroidKeyStore");
        } catch (NoSuchAlgorithmException |
                NoSuchProviderException e) {
            throw new RuntimeException(
                    "Problém inštancie KeyGenerator", e);
        }
 
        try {
            keyStore.load(null);
            kg.init(new
                    KeyGenParameterSpec.Builder(KEY_NAME,
                    KeyProperties.PURPOSE_ENCRYPT |
                            KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(
                            KeyProperties.ENCRYPTION_PADDING_PKCS7)
                    .build());
            kg.generateKey();
        } catch (NoSuchAlgorithmException |
                InvalidAlgorithmParameterException
                | CertificateException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Teraz môžete aplikáciu vyskúšať. Dá sa to aj na emulátore, avšak aj tu musíte autentifikáciu najskôr nastaviť.

V emulátore simulujeme pritlačenie prsta

Teraz spustíme aplikáciu a nasimulujeme priloženie prsta na snímač

Úspešné prihlásenie

Rekapitulácia seriálu

1  – Prvá aplikácia 

2 – Možnosti emulátorov 

3 - Zorientujte sa v projekte aplikácie

4 – Princípy dizajnu a škálovania

5 – Uporiadanie prvkov používateľského rozhrania

6 – Obsluha udalostí

7 – Aplikácia s dvomi aktivitami  

8 – Spustenie na reálnom zariadení

9 – Intenty, alebo kto to urobí

10 – Dotyky a gestá

11 - Dotyky a gestá II  

12  - Zmena orientácie displeja

13 – Grafika 1

14 – Grafika II

15 - Animácia

16 – Animácia II

17 – Prehrávanie zvuku a videa

18 – Senzory - využitie údajov z akcelerometra

Zobrazit Galériu

Luboslav Lacko

Všetky autorove články
vývoj pre android Android aplikácia

1 komentár

odtlacok je login, nie password reakcia na: Naučte sa vyvíjať Android aplikácie – snímanie odtlačkov prstov

23.4.2020 10:04
kedze odtlacok nevieme zmenit, je to ID (login) a nie heslo
Reagovať

Pridať komentár

Mohlo by vás zaujímať

Mohlo by vás zaujímať